1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_hal_ospi.c
4   * @author  MCD Application Team
5   * @brief   OSPI HAL module driver.
6              This file provides firmware functions to manage the following
7              functionalities of the OctoSPI interface (OSPI).
8               + Initialization and de-initialization functions
9               + Hyperbus configuration
10               + Indirect functional mode management
11               + Memory-mapped functional mode management
12               + Auto-polling functional mode management
13               + Interrupts and flags management
14               + DMA channel configuration for indirect functional mode
15               + Errors management and abort functionality
16               + IO manager configuration
17 
18   @verbatim
19  ===============================================================================
20                         ##### How to use this driver #####
21  ===============================================================================
22   [..]
23     *** Initialization ***
24     ======================
25     [..]
26       (#) As prerequisite, fill in the HAL_OSPI_MspInit() :
27         (++) Enable OctoSPI and OctoSPIM clocks interface with __HAL_RCC_OSPIx_CLK_ENABLE().
28         (++) Reset OctoSPI IP with __HAL_RCC_OSPIx_FORCE_RESET() and __HAL_RCC_OSPIx_RELEASE_RESET().
29         (++) Enable the clocks for the OctoSPI GPIOS with __HAL_RCC_GPIOx_CLK_ENABLE().
30         (++) Configure these OctoSPI pins in alternate mode using HAL_GPIO_Init().
31         (++) If interrupt or DMA mode is used, enable and configure OctoSPI global
32             interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
33         (++) If DMA mode is used, enable the clocks for the OctoSPI DMA channel
34             with __HAL_RCC_DMAx_CLK_ENABLE(), configure DMA with HAL_DMA_Init(),
35             link it with OctoSPI handle using __HAL_LINKDMA(), enable and configure
36             DMA channel global interrupt with HAL_NVIC_SetPriority() and HAL_NVIC_EnableIRQ().
37       (#) Configure the fifo threshold, the dual-quad mode, the memory type, the
38           device size, the CS high time, the free running clock, the clock mode,
39           the wrap size, the clock prescaler, the sample shifting, the hold delay
40           and the CS boundary using the HAL_OSPI_Init() function.
41       (#) When using Hyperbus, configure the RW recovery time, the access time,
42           the write latency and the latency mode unsing the HAL_OSPI_HyperbusCfg()
43           function.
44 
45     *** Indirect functional mode ***
46     ================================
47     [..]
48       (#) In regular mode, configure the command sequence using the HAL_OSPI_Command()
49           or HAL_OSPI_Command_IT() functions :
50          (++) Instruction phase : the mode used and if present the size, the instruction
51               opcode and the DTR mode.
52          (++) Address phase : the mode used and if present the size, the address
53               value and the DTR mode.
54          (++) Alternate-bytes phase : the mode used and if present the size, the
55               alternate bytes values and the DTR mode.
56          (++) Dummy-cycles phase : the number of dummy cycles (mode used is same as data phase).
57          (++) Data phase : the mode used and if present the number of bytes and the DTR mode.
58          (++) Data strobe (DQS) mode : the activation (or not) of this mode
59          (++) Sending Instruction Only Once (SIOO) mode : the activation (or not) of this mode.
60          (++) Flash identifier : in dual-quad mode, indicates which flash is concerned
61          (++) Operation type : always common configuration
62       (#) In Hyperbus mode, configure the command sequence using the HAL_OSPI_HyperbusCmd()
63           function :
64          (++) Address space : indicate if the access will be done in register or memory
65          (++) Address size
66          (++) Number of data
67          (++) Data strobe (DQS) mode : the activation (or not) of this mode
68       (#) If no data is required for the command (only for regular mode, not for
69           Hyperbus mode), it is sent directly to the memory :
70          (++) In polling mode, the output of the function is done when the transfer is complete.
71          (++) In interrupt mode, HAL_OSPI_CmdCpltCallback() will be called when the transfer is complete.
72       (#) For the indirect write mode, use HAL_OSPI_Transmit(), HAL_OSPI_Transmit_DMA() or
73           HAL_OSPI_Transmit_IT() after the command configuration :
74          (++) In polling mode, the output of the function is done when the transfer is complete.
75          (++) In interrupt mode, HAL_OSPI_FifoThresholdCallback() will be called when the fifo threshold
76              is reached and HAL_OSPI_TxCpltCallback() will be called when the transfer is complete.
77          (++) In DMA mode, HAL_OSPI_TxHalfCpltCallback() will be called at the half transfer and
78              HAL_OSPI_TxCpltCallback() will be called when the transfer is complete.
79       (#) For the indirect read mode, use HAL_OSPI_Receive(), HAL_OSPI_Receive_DMA() or
80           HAL_OSPI_Receive_IT() after the command configuration :
81          (++) In polling mode, the output of the function is done when the transfer is complete.
82          (++) In interrupt mode, HAL_OSPI_FifoThresholdCallback() will be called when the fifo threshold
83              is reached and HAL_OSPI_RxCpltCallback() will be called when the transfer is complete.
84          (++) In DMA mode, HAL_OSPI_RxHalfCpltCallback() will be called at the half transfer and
85              HAL_OSPI_RxCpltCallback() will be called when the transfer is complete.
86 
87     *** Auto-polling functional mode ***
88     ====================================
89     [..]
90       (#) Configure the command sequence by the same way than the indirect mode
91       (#) Configure the auto-polling functional mode using the HAL_OSPI_AutoPolling()
92           or HAL_OSPI_AutoPolling_IT() functions :
93          (++) The size of the status bytes, the match value, the mask used, the match mode (OR/AND),
94              the polling interval and the automatic stop activation.
95       (#) After the configuration :
96          (++) In polling mode, the output of the function is done when the status match is reached. The
97              automatic stop is activated to avoid an infinite loop.
98          (++) In interrupt mode, HAL_OSPI_StatusMatchCallback() will be called each time the status match is reached.
99 
100     *** Memory-mapped functional mode ***
101     =====================================
102     [..]
103       (#) Configure the command sequence by the same way than the indirect mode except
104           for the operation type in regular mode :
105          (++) Operation type equals to read configuration : the command configuration
106               applies to read access in memory-mapped mode
107          (++) Operation type equals to write configuration : the command configuration
108               applies to write access in memory-mapped mode
109          (++) Both read and write configuration should be performed before activating
110               memory-mapped mode
111       (#) Configure the memory-mapped functional mode using the HAL_OSPI_MemoryMapped()
112           functions :
113          (++) The timeout activation and the timeout period.
114       (#) After the configuration, the OctoSPI will be used as soon as an access on the AHB is done on
115           the address range. HAL_OSPI_TimeOutCallback() will be called when the timeout expires.
116 
117     *** Errors management and abort functionality ***
118     =================================================
119     [..]
120       (#) HAL_OSPI_GetError() function gives the error raised during the last operation.
121       (#) HAL_OSPI_Abort() and HAL_OSPI_AbortIT() functions aborts any on-going operation and
122           flushes the fifo :
123          (++) In polling mode, the output of the function is done when the transfer
124               complete bit is set and the busy bit cleared.
125          (++) In interrupt mode, HAL_OSPI_AbortCpltCallback() will be called when
126               the transfer complete bit is set.
127 
128     *** Control functions ***
129     =========================
130     [..]
131       (#) HAL_OSPI_GetState() function gives the current state of the HAL OctoSPI driver.
132       (#) HAL_OSPI_SetTimeout() function configures the timeout value used in the driver.
133       (#) HAL_OSPI_SetFifoThreshold() function configures the threshold on the Fifo of the OSPI IP.
134       (#) HAL_OSPI_GetFifoThreshold() function gives the current of the Fifo's threshold
135 
136     *** IO manager configuration functions ***
137     ==========================================
138     [..]
139       (#) HAL_OSPIM_Config() function configures the IO manager for the OctoSPI instance.
140 
141     *** Callback registration ***
142     =============================================
143     [..]
144       The compilation define  USE_HAL_OSPI_REGISTER_CALLBACKS when set to 1
145       allows the user to configure dynamically the driver callbacks.
146 
147       Use Functions @ref HAL_OSPI_RegisterCallback() to register a user callback,
148       it allows to register following callbacks:
149         (+) ErrorCallback : callback when error occurs.
150         (+) AbortCpltCallback : callback when abort is completed.
151         (+) FifoThresholdCallback : callback when the fifo threshold is reached.
152         (+) CmdCpltCallback : callback when a command without data is completed.
153         (+) RxCpltCallback : callback when a reception transfer is completed.
154         (+) TxCpltCallback : callback when a transmission transfer is completed.
155         (+) RxHalfCpltCallback : callback when half of the reception transfer is completed.
156         (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed.
157         (+) StatusMatchCallback : callback when a status match occurs.
158         (+) TimeOutCallback : callback when the timeout perioed expires.
159         (+) MspInitCallback    : OSPI MspInit.
160         (+) MspDeInitCallback  : OSPI MspDeInit.
161       This function takes as parameters the HAL peripheral handle, the Callback ID
162       and a pointer to the user callback function.
163 
164       Use function @ref HAL_OSPI_UnRegisterCallback() to reset a callback to the default
165       weak (surcharged) function. It allows to reset following callbacks:
166         (+) ErrorCallback : callback when error occurs.
167         (+) AbortCpltCallback : callback when abort is completed.
168         (+) FifoThresholdCallback : callback when the fifo threshold is reached.
169         (+) CmdCpltCallback : callback when a command without data is completed.
170         (+) RxCpltCallback : callback when a reception transfer is completed.
171         (+) TxCpltCallback : callback when a transmission transfer is completed.
172         (+) RxHalfCpltCallback : callback when half of the reception transfer is completed.
173         (+) TxHalfCpltCallback : callback when half of the transmission transfer is completed.
174         (+) StatusMatchCallback : callback when a status match occurs.
175         (+) TimeOutCallback : callback when the timeout perioed expires.
176         (+) MspInitCallback    : OSPI MspInit.
177         (+) MspDeInitCallback  : OSPI MspDeInit.
178       This function) takes as parameters the HAL peripheral handle and the Callback ID.
179 
180       By default, after the @ref HAL_OSPI_Init and if the state is HAL_OSPI_STATE_RESET
181       all callbacks are reset to the corresponding legacy weak (surcharged) functions.
182       Exception done for MspInit and MspDeInit callbacks that are respectively
183       reset to the legacy weak (surcharged) functions in the @ref HAL_OSPI_Init
184       and @ref  HAL_OSPI_DeInit only when these callbacks are null (not registered beforehand).
185       If not, MspInit or MspDeInit are not null, the @ref HAL_OSPI_Init and @ref HAL_OSPI_DeInit
186       keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
187 
188       Callbacks can be registered/unregistered in READY state only.
189       Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
190       in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
191       during the Init/DeInit.
192       In that case first register the MspInit/MspDeInit user callbacks
193       using @ref HAL_OSPI_RegisterCallback before calling @ref HAL_OSPI_DeInit
194       or @ref HAL_OSPI_Init function.
195 
196       When The compilation define USE_HAL_OSPI_REGISTER_CALLBACKS is set to 0 or
197       not defined, the callback registering feature is not available
198       and weak (surcharged) callbacks are used.
199 
200   @endverbatim
201   ******************************************************************************
202   * @attention
203   *
204   * <h2><center>&copy; COPYRIGHT(c) 2018 STMicroelectronics</center></h2>
205   *
206   * Redistribution and use in source and binary forms, with or without modification,
207   * are permitted provided that the following conditions are met:
208   *   1. Redistributions of source code must retain the above copyright notice,
209   *      this list of conditions and the following disclaimer.
210   *   2. Redistributions in binary form must reproduce the above copyright notice,
211   *      this list of conditions and the following disclaimer in the documentation
212   *      and/or other materials provided with the distribution.
213   *   3. Neither the name of STMicroelectronics nor the names of its contributors
214   *      may be used to endorse or promote products derived from this software
215   *      without specific prior written permission.
216   *
217   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
218   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
220   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
221   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
222   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
223   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
224   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
225   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
226   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
227   *
228   ******************************************************************************
229   */
230 
231 /* Includes ------------------------------------------------------------------*/
232 #include "stm32l4xx_hal.h"
233 
234 #if defined(OCTOSPI) || defined(OCTOSPI1) || defined(OCTOSPI2)
235 
236 /** @addtogroup STM32L4xx_HAL_Driver
237   * @{
238   */
239 
240 /** @defgroup OSPI OSPI
241   * @brief OSPI HAL module driver
242   * @{
243   */
244 
245 #ifdef HAL_OSPI_MODULE_ENABLED
246 
247 /**
248   @cond 0
249   */
250 /* Private typedef -----------------------------------------------------------*/
251 
252 /* Private define ------------------------------------------------------------*/
253 #define OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE ((uint32_t)0x00000000)         /*!< Indirect write mode    */
254 #define OSPI_FUNCTIONAL_MODE_INDIRECT_READ  ((uint32_t)OCTOSPI_CR_FMODE_0) /*!< Indirect read mode     */
255 #define OSPI_FUNCTIONAL_MODE_AUTO_POLLING   ((uint32_t)OCTOSPI_CR_FMODE_1) /*!< Automatic polling mode */
256 #define OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED  ((uint32_t)OCTOSPI_CR_FMODE)   /*!< Memory-mapped mode     */
257 
258 #define OSPI_CFG_STATE_MASK  0x00000004U
259 #define OSPI_BUSY_STATE_MASK 0x00000008U
260 
261 #define OSPI_NB_INSTANCE   2U
262 #define OSPI_IOM_NB_PORTS  2U
263 #define OSPI_IOM_PORT_MASK 0x1U
264 
265 /* Private macro -------------------------------------------------------------*/
266 #define IS_OSPI_FUNCTIONAL_MODE(MODE) (((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE) || \
267                                        ((MODE) == OSPI_FUNCTIONAL_MODE_INDIRECT_READ)  || \
268                                        ((MODE) == OSPI_FUNCTIONAL_MODE_AUTO_POLLING)   || \
269                                        ((MODE) == OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED))
270 
271 /* Private variables ---------------------------------------------------------*/
272 
273 /* Private function prototypes -----------------------------------------------*/
274 static void              OSPI_DMACplt                  (DMA_HandleTypeDef *hdma);
275 static void              OSPI_DMAHalfCplt              (DMA_HandleTypeDef *hdma);
276 static void              OSPI_DMAError                 (DMA_HandleTypeDef *hdma);
277 static void              OSPI_DMAAbortCplt             (DMA_HandleTypeDef *hdma);
278 static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag, FlagStatus State, uint32_t Tickstart, uint32_t Timeout);
279 static HAL_StatusTypeDef OSPI_ConfigCmd                (OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd);
280 static HAL_StatusTypeDef OSPIM_GetConfig               (uint8_t instance_nb, OSPIM_CfgTypeDef *cfg);
281 /**
282   @endcond
283   */
284 
285 /* Exported functions --------------------------------------------------------*/
286 
287 /** @defgroup OSPI_Exported_Functions OSPI Exported Functions
288   * @{
289   */
290 
291 /** @defgroup OSPI_Exported_Functions_Group1 Initialization/de-initialization functions
292   * @brief    Initialization and Configuration functions
293   *
294 @verbatim
295 ===============================================================================
296             ##### Initialization and Configuration functions #####
297  ===============================================================================
298     [..]
299     This subsection provides a set of functions allowing to :
300       (+) Initialize the OctoSPI.
301       (+) De-initialize the OctoSPI.
302 
303 @endverbatim
304   * @{
305   */
306 
307 /**
308   * @brief  Initialize the OSPI mode according to the specified parameters
309   *         in the OSPI_InitTypeDef and initialize the associated handle.
310   * @param  hospi : OSPI handle
311   * @retval HAL status
312   */
HAL_OSPI_Init(OSPI_HandleTypeDef * hospi)313 HAL_StatusTypeDef HAL_OSPI_Init (OSPI_HandleTypeDef *hospi)
314 {
315   HAL_StatusTypeDef status = HAL_OK;
316   uint32_t tickstart = HAL_GetTick();
317 
318   /* Check the OSPI handle allocation */
319   if (hospi == NULL)
320   {
321     status = HAL_ERROR;
322     /* No error code can be set set as the handler is null */
323   }
324   else
325   {
326     /* Check the parameters of the initialization structure */
327     assert_param(IS_OSPI_FIFO_THRESHOLD (hospi->Init.FifoThreshold));
328     assert_param(IS_OSPI_DUALQUAD_MODE  (hospi->Init.DualQuad));
329     assert_param(IS_OSPI_MEMORY_TYPE    (hospi->Init.MemoryType));
330     assert_param(IS_OSPI_DEVICE_SIZE    (hospi->Init.DeviceSize));
331     assert_param(IS_OSPI_CS_HIGH_TIME   (hospi->Init.ChipSelectHighTime));
332     assert_param(IS_OSPI_FREE_RUN_CLK   (hospi->Init.FreeRunningClock));
333     assert_param(IS_OSPI_CLOCK_MODE     (hospi->Init.ClockMode));
334     assert_param(IS_OSPI_WRAP_SIZE      (hospi->Init.WrapSize));
335     assert_param(IS_OSPI_CLK_PRESCALER  (hospi->Init.ClockPrescaler));
336     assert_param(IS_OSPI_SAMPLE_SHIFTING(hospi->Init.SampleShifting));
337     assert_param(IS_OSPI_DHQC           (hospi->Init.DelayHoldQuarterCycle));
338     assert_param(IS_OSPI_CS_BOUNDARY    (hospi->Init.ChipSelectBoundary));
339 
340     /* Initialize error code */
341     hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
342 
343     /* Check if the state is the reset state */
344     if (hospi->State == HAL_OSPI_STATE_RESET)
345     {
346 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
347       /* Reset Callback pointers in HAL_OSPI_STATE_RESET only */
348       hospi->ErrorCallback         = HAL_OSPI_ErrorCallback;
349       hospi->AbortCpltCallback     = HAL_OSPI_AbortCpltCallback;
350       hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback;
351       hospi->CmdCpltCallback       = HAL_OSPI_CmdCpltCallback;
352       hospi->RxCpltCallback        = HAL_OSPI_RxCpltCallback;
353       hospi->TxCpltCallback        = HAL_OSPI_TxCpltCallback;
354       hospi->RxHalfCpltCallback    = HAL_OSPI_RxHalfCpltCallback;
355       hospi->TxHalfCpltCallback    = HAL_OSPI_TxHalfCpltCallback;
356       hospi->StatusMatchCallback   = HAL_OSPI_StatusMatchCallback;
357       hospi->TimeOutCallback       = HAL_OSPI_TimeOutCallback;
358 
359       if(hospi->MspInitCallback == NULL)
360       {
361         hospi->MspInitCallback = HAL_OSPI_MspInit;
362       }
363 
364       /* Init the low level hardware */
365       hospi->MspInitCallback(hospi);
366 #else
367       /* Initialization of the low level hardware */
368       HAL_OSPI_MspInit(hospi);
369 #endif
370 
371       /* Configure the default timeout for the OSPI memory access */
372       status = HAL_OSPI_SetTimeout(hospi, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
373     }
374 
375     if (status == HAL_OK)
376     {
377      /* Configure memory type, device size, chip select high time, free running clock, clock mode */
378       MODIFY_REG(hospi->Instance->DCR1, (OCTOSPI_DCR1_MTYP | OCTOSPI_DCR1_DEVSIZE | OCTOSPI_DCR1_CSHT | OCTOSPI_DCR1_FRCK | OCTOSPI_DCR1_CKMODE),
379                  (hospi->Init.MemoryType | ((hospi->Init.DeviceSize - 1U) << OCTOSPI_DCR1_DEVSIZE_Pos) |
380                   ((hospi->Init.ChipSelectHighTime - 1U) << OCTOSPI_DCR1_CSHT_Pos) | hospi->Init.FreeRunningClock |
381                   hospi->Init.ClockMode));
382 
383       /* Configure wrap size */
384       MODIFY_REG(hospi->Instance->DCR2, OCTOSPI_DCR2_WRAPSIZE, hospi->Init.WrapSize);
385 
386       /* Configure chip select boundary */
387       hospi->Instance->DCR3 = (hospi->Init.ChipSelectBoundary << OCTOSPI_DCR3_CSBOUND_Pos);
388 
389 
390       /* Configure FIFO threshold */
391       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold - 1U) << OCTOSPI_CR_FTHRES_Pos));
392 
393       /* Wait till busy flag is reset */
394       status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
395 
396       if (status == HAL_OK)
397       {
398          /* Configure clock prescaler */
399          MODIFY_REG(hospi->Instance->DCR2, OCTOSPI_DCR2_PRESCALER, ((hospi->Init.ClockPrescaler - 1U) << OCTOSPI_DCR2_PRESCALER_Pos));
400 
401          /* Configure Dual Quad mode */
402          MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_DQM, hospi->Init.DualQuad);
403 
404          /* Configure sample shifting and delay hold quarter cycle */
405          MODIFY_REG(hospi->Instance->TCR, (OCTOSPI_TCR_SSHIFT | OCTOSPI_TCR_DHQC), (hospi->Init.SampleShifting | hospi->Init.DelayHoldQuarterCycle));
406 
407          /* Enable OctoSPI */
408          __HAL_OSPI_ENABLE(hospi);
409 
410          /* Initialize the OSPI state */
411          if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
412          {
413             hospi->State = HAL_OSPI_STATE_HYPERBUS_INIT;
414          }
415          else
416          {
417             hospi->State = HAL_OSPI_STATE_READY;
418          }
419       }
420     }
421   }
422 
423   /* Return function status */
424   return status;
425 }
426 
427 /**
428   * @brief  Initialize the OSPI MSP.
429   * @param  hospi : OSPI handle
430   * @retval None
431   */
HAL_OSPI_MspInit(OSPI_HandleTypeDef * hospi)432 __weak void HAL_OSPI_MspInit(OSPI_HandleTypeDef *hospi)
433 {
434   /* Prevent unused argument(s) compilation warning */
435   UNUSED(hospi);
436 
437   /* NOTE : This function should not be modified, when the callback is needed,
438             the HAL_OSPI_MspInit can be implemented in the user file
439    */
440 }
441 
442 /**
443   * @brief  De-Initialize the OSPI peripheral.
444   * @param  hospi : OSPI handle
445   * @retval HAL status
446   */
HAL_OSPI_DeInit(OSPI_HandleTypeDef * hospi)447 HAL_StatusTypeDef HAL_OSPI_DeInit(OSPI_HandleTypeDef *hospi)
448 {
449   HAL_StatusTypeDef status = HAL_OK;
450 
451   /* Check the OSPI handle allocation */
452   if (hospi == NULL)
453   {
454     status = HAL_ERROR;
455     /* No error code can be set set as the handler is null */
456   }
457   else
458   {
459      /* Disable OctoSPI */
460      __HAL_OSPI_DISABLE(hospi);
461 
462 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
463      if(hospi->MspDeInitCallback == NULL)
464      {
465        hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
466      }
467 
468      /* DeInit the low level hardware */
469      hospi->MspDeInitCallback(hospi);
470 #else
471      /* De-initialize the low-level hardware */
472      HAL_OSPI_MspDeInit(hospi);
473 #endif
474 
475      /* Reset the driver state */
476      hospi->State = HAL_OSPI_STATE_RESET;
477   }
478 
479   return status;
480 }
481 
482 /**
483   * @brief  DeInitialize the OSPI MSP.
484   * @param  hospi : OSPI handle
485   * @retval None
486   */
HAL_OSPI_MspDeInit(OSPI_HandleTypeDef * hospi)487 __weak void HAL_OSPI_MspDeInit(OSPI_HandleTypeDef *hospi)
488 {
489   /* Prevent unused argument(s) compilation warning */
490   UNUSED(hospi);
491 
492   /* NOTE : This function should not be modified, when the callback is needed,
493             the HAL_OSPI_MspDeInit can be implemented in the user file
494    */
495 }
496 
497 /**
498   * @}
499   */
500 
501 /** @defgroup OSPI_Exported_Functions_Group2 Input and Output operation functions
502   *  @brief OSPI Transmit/Receive functions
503   *
504 @verbatim
505  ===============================================================================
506                       ##### IO operation functions #####
507  ===============================================================================
508     [..]
509     This subsection provides a set of functions allowing to :
510       (+) Handle the interrupts.
511       (+) Handle the command sequence (regular and Hyperbus).
512       (+) Handle the Hyperbus configuration.
513       (+) Transmit data in blocking, interrupt or DMA mode.
514       (+) Receive data in blocking, interrupt or DMA mode.
515       (+) Manage the auto-polling functional mode.
516       (+) Manage the memory-mapped functional mode.
517 
518 @endverbatim
519   * @{
520   */
521 
522 /**
523   * @brief  Handle OSPI interrupt request.
524   * @param  hospi : OSPI handle
525   * @retval None
526   */
HAL_OSPI_IRQHandler(OSPI_HandleTypeDef * hospi)527 void HAL_OSPI_IRQHandler(OSPI_HandleTypeDef *hospi)
528 {
529   __IO uint32_t *data_reg = &hospi->Instance->DR;
530   uint32_t flag           = hospi->Instance->SR;
531   uint32_t itsource       = hospi->Instance->CR;
532   uint32_t currentstate   = hospi->State;
533 
534   /* OctoSPI fifo threshold interrupt occurred -------------------------------*/
535   if (((flag & HAL_OSPI_FLAG_FT) != 0U) && ((itsource & HAL_OSPI_IT_FT) != 0U))
536   {
537     if (currentstate == HAL_OSPI_STATE_BUSY_TX)
538     {
539       /* Write a data in the fifo */
540       *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr;
541       hospi->pBuffPtr++;
542       hospi->XferCount--;
543     }
544     else if (currentstate == HAL_OSPI_STATE_BUSY_RX)
545     {
546       /* Read a data from the fifo */
547       *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
548       hospi->pBuffPtr++;
549       hospi->XferCount--;
550     }
551     else
552     {
553       /* Nothing to do */
554     }
555 
556     if (hospi->XferCount == 0U)
557     {
558       /* All data have been received or transmitted for the transfer */
559       /* Disable fifo threshold interrupt */
560       __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_FT);
561     }
562 
563     /* Fifo threshold callback */
564 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
565     hospi->FifoThresholdCallback(hospi);
566 #else
567     HAL_OSPI_FifoThresholdCallback(hospi);
568 #endif
569   }
570   /* OctoSPI transfer complete interrupt occurred ----------------------------*/
571   else if (((flag & HAL_OSPI_FLAG_TC) != 0U) && ((itsource & HAL_OSPI_IT_TC) != 0U))
572   {
573     if (currentstate == HAL_OSPI_STATE_BUSY_RX)
574     {
575       if ((hospi->XferCount > 0U) && ((flag & OCTOSPI_SR_FLEVEL) != 0U))
576       {
577         /* Read the last data received in the fifo */
578         *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
579         hospi->pBuffPtr++;
580         hospi->XferCount--;
581       }
582       else if(hospi->XferCount == 0U)
583       {
584         /* Clear flag */
585         hospi->Instance->FCR = HAL_OSPI_FLAG_TC;
586 
587         /* Disable the interrupts */
588         __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
589 
590         /* Update state */
591         hospi->State = HAL_OSPI_STATE_READY;
592 
593         /* RX complete callback */
594 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
595         hospi->RxCpltCallback(hospi);
596 #else
597         HAL_OSPI_RxCpltCallback(hospi);
598 #endif
599       }
600       else
601       {
602         /* Nothing to do */
603       }
604     }
605     else
606     {
607       /* Clear flag */
608       hospi->Instance->FCR = HAL_OSPI_FLAG_TC;
609 
610       /* Disable the interrupts */
611       __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
612 
613       /* Update state */
614       hospi->State = HAL_OSPI_STATE_READY;
615 
616       if (currentstate == HAL_OSPI_STATE_BUSY_TX)
617       {
618         /* TX complete callback */
619 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
620         hospi->TxCpltCallback(hospi);
621 #else
622         HAL_OSPI_TxCpltCallback(hospi);
623 #endif
624       }
625       else if (currentstate == HAL_OSPI_STATE_BUSY_CMD)
626       {
627         /* Command complete callback */
628 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
629         hospi->CmdCpltCallback(hospi);
630 #else
631         HAL_OSPI_CmdCpltCallback(hospi);
632 #endif
633       }
634       else if (currentstate == HAL_OSPI_STATE_ABORT)
635       {
636         if (hospi->ErrorCode == HAL_OSPI_ERROR_NONE)
637         {
638           /* Abort called by the user */
639           /* Abort complete callback */
640 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
641           hospi->AbortCpltCallback(hospi);
642 #else
643           HAL_OSPI_AbortCpltCallback(hospi);
644 #endif
645         }
646         else
647         {
648           /* Abort due to an error (eg : DMA error) */
649           /* Error callback */
650 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
651           hospi->ErrorCallback(hospi);
652 #else
653           HAL_OSPI_ErrorCallback(hospi);
654 #endif
655         }
656       }
657       else
658       {
659         /* Nothing to do */
660       }
661     }
662   }
663   /* OctoSPI status match interrupt occurred ---------------------------------*/
664   else if (((flag & HAL_OSPI_FLAG_SM) != 0U) && ((itsource & HAL_OSPI_IT_SM) != 0U))
665   {
666     /* Clear flag */
667     hospi->Instance->FCR = HAL_OSPI_FLAG_SM;
668 
669     /* Check if automatic poll mode stop is activated */
670     if ((hospi->Instance->CR & OCTOSPI_CR_APMS) != 0U)
671     {
672       /* Disable the interrupts */
673       __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE);
674 
675       /* Update state */
676       hospi->State = HAL_OSPI_STATE_READY;
677     }
678 
679     /* Status match callback */
680 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
681     hospi->StatusMatchCallback(hospi);
682 #else
683     HAL_OSPI_StatusMatchCallback(hospi);
684 #endif
685   }
686   /* OctoSPI transfer error interrupt occurred -------------------------------*/
687   else if (((flag & HAL_OSPI_FLAG_TE) != 0U) && ((itsource & HAL_OSPI_IT_TE) != 0U))
688   {
689     /* Clear flag */
690     hospi->Instance->FCR = HAL_OSPI_FLAG_TE;
691 
692     /* Disable all interrupts */
693     __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE));
694 
695     /* Set error code */
696     hospi->ErrorCode = HAL_OSPI_ERROR_TRANSFER;
697 
698     /* Check if the DMA is enabled */
699     if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
700     {
701       /* Disable the DMA transfer on the OctoSPI side */
702       CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
703 
704       /* Disable the DMA transfer on the DMA side */
705       hospi->hdma->XferAbortCallback = OSPI_DMAAbortCplt;
706       if (HAL_DMA_Abort_IT(hospi->hdma) != HAL_OK)
707       {
708         /* Update state */
709         hospi->State = HAL_OSPI_STATE_READY;
710 
711         /* Error callback */
712 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
713         hospi->ErrorCallback(hospi);
714 #else
715         HAL_OSPI_ErrorCallback(hospi);
716 #endif
717       }
718     }
719     else
720     {
721       /* Update state */
722       hospi->State = HAL_OSPI_STATE_READY;
723 
724       /* Error callback */
725 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
726       hospi->ErrorCallback(hospi);
727 #else
728       HAL_OSPI_ErrorCallback(hospi);
729 #endif
730     }
731   }
732   /* OctoSPI timeout interrupt occurred --------------------------------------*/
733   else if (((flag & HAL_OSPI_FLAG_TO) != 0U) && ((itsource & HAL_OSPI_IT_TO) != 0U))
734   {
735     /* Clear flag */
736     hospi->Instance->FCR = HAL_OSPI_FLAG_TO;
737 
738     /* Timeout callback */
739 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
740     hospi->TimeOutCallback(hospi);
741 #else
742     HAL_OSPI_TimeOutCallback(hospi);
743 #endif
744   }
745   else
746   {
747     /* Nothing to do */
748   }
749 }
750 
751 /**
752   * @brief  Set the command configuration.
753   * @param  hospi   : OSPI handle
754   * @param  cmd     : structure that contains the command configuration information
755   * @param  Timeout : Timeout duration
756   * @retval HAL status
757   */
HAL_OSPI_Command(OSPI_HandleTypeDef * hospi,OSPI_RegularCmdTypeDef * cmd,uint32_t Timeout)758 HAL_StatusTypeDef HAL_OSPI_Command(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd, uint32_t Timeout)
759 {
760   HAL_StatusTypeDef status;
761   uint32_t state;
762   uint32_t tickstart = HAL_GetTick();
763 
764   /* Check the parameters of the command structure */
765   assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType));
766 
767   if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
768   {
769     assert_param(IS_OSPI_FLASH_ID(cmd->FlashId));
770   }
771 
772   assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode));
773   if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
774   {
775     assert_param(IS_OSPI_INSTRUCTION_SIZE    (cmd->InstructionSize));
776     assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode));
777   }
778 
779   assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode));
780   if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
781   {
782     assert_param(IS_OSPI_ADDRESS_SIZE    (cmd->AddressSize));
783     assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode));
784   }
785 
786   assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode));
787   if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
788   {
789     assert_param(IS_OSPI_ALT_BYTES_SIZE    (cmd->AlternateBytesSize));
790     assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode));
791   }
792 
793   assert_param(IS_OSPI_DATA_MODE(cmd->DataMode));
794   if (cmd->DataMode != HAL_OSPI_DATA_NONE)
795   {
796     if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
797     {
798       assert_param(IS_OSPI_NUMBER_DATA  (cmd->NbData));
799     }
800     assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode));
801     assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles));
802   }
803 
804   assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode));
805   assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode));
806 
807   /* Check the state of the driver */
808   state = hospi->State;
809   if (((state == HAL_OSPI_STATE_READY)         && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS)) ||
810       ((state == HAL_OSPI_STATE_READ_CMD_CFG)  && (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG))     ||
811       ((state == HAL_OSPI_STATE_WRITE_CMD_CFG) && (cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG)))
812   {
813     /* Wait till busy flag is reset */
814     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
815 
816     if (status == HAL_OK)
817     {
818       /* Initialize error code */
819       hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
820 
821       /* Configure the registers */
822       status = OSPI_ConfigCmd(hospi, cmd);
823 
824       if (status == HAL_OK)
825       {
826         if (cmd->DataMode == HAL_OSPI_DATA_NONE)
827         {
828           /* When there is no data phase, the transfer start as soon as the configuration is done
829              so wait until TC flag is set to go back in idle state */
830           status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
831 
832           __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
833         }
834         else
835         {
836           /* Update the state */
837           if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
838           {
839             hospi->State = HAL_OSPI_STATE_CMD_CFG;
840           }
841           else if (cmd->OperationType == HAL_OSPI_OPTYPE_READ_CFG)
842           {
843             if (hospi->State == HAL_OSPI_STATE_WRITE_CMD_CFG)
844             {
845               hospi->State = HAL_OSPI_STATE_CMD_CFG;
846             }
847             else
848             {
849               hospi->State = HAL_OSPI_STATE_READ_CMD_CFG;
850             }
851           }
852           else
853           {
854             if (hospi->State == HAL_OSPI_STATE_READ_CMD_CFG)
855             {
856               hospi->State = HAL_OSPI_STATE_CMD_CFG;
857             }
858             else
859             {
860               hospi->State = HAL_OSPI_STATE_WRITE_CMD_CFG;
861             }
862           }
863         }
864       }
865     }
866   }
867   else
868   {
869     status = HAL_ERROR;
870     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
871   }
872 
873   /* Return function status */
874   return status;
875 }
876 
877 /**
878   * @brief  Set the command configuration in interrupt mode.
879   * @param  hospi : OSPI handle
880   * @param  cmd   : structure that contains the command configuration information
881   * @note   This function is used only in Indirect Read or Write Modes
882   * @retval HAL status
883   */
HAL_OSPI_Command_IT(OSPI_HandleTypeDef * hospi,OSPI_RegularCmdTypeDef * cmd)884 HAL_StatusTypeDef HAL_OSPI_Command_IT(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd)
885 {
886   HAL_StatusTypeDef status;
887   uint32_t tickstart = HAL_GetTick();
888 
889   /* Check the parameters of the command structure */
890   assert_param(IS_OSPI_OPERATION_TYPE(cmd->OperationType));
891 
892   if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
893   {
894     assert_param(IS_OSPI_FLASH_ID(cmd->FlashId));
895   }
896 
897   assert_param(IS_OSPI_INSTRUCTION_MODE(cmd->InstructionMode));
898   if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
899   {
900     assert_param(IS_OSPI_INSTRUCTION_SIZE    (cmd->InstructionSize));
901     assert_param(IS_OSPI_INSTRUCTION_DTR_MODE(cmd->InstructionDtrMode));
902   }
903 
904   assert_param(IS_OSPI_ADDRESS_MODE(cmd->AddressMode));
905   if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
906   {
907     assert_param(IS_OSPI_ADDRESS_SIZE    (cmd->AddressSize));
908     assert_param(IS_OSPI_ADDRESS_DTR_MODE(cmd->AddressDtrMode));
909   }
910 
911   assert_param(IS_OSPI_ALT_BYTES_MODE(cmd->AlternateBytesMode));
912   if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
913   {
914     assert_param(IS_OSPI_ALT_BYTES_SIZE    (cmd->AlternateBytesSize));
915     assert_param(IS_OSPI_ALT_BYTES_DTR_MODE(cmd->AlternateBytesDtrMode));
916   }
917 
918   assert_param(IS_OSPI_DATA_MODE(cmd->DataMode));
919   if (cmd->DataMode != HAL_OSPI_DATA_NONE)
920   {
921     assert_param(IS_OSPI_NUMBER_DATA  (cmd->NbData));
922     assert_param(IS_OSPI_DATA_DTR_MODE(cmd->DataDtrMode));
923     assert_param(IS_OSPI_DUMMY_CYCLES (cmd->DummyCycles));
924   }
925 
926   assert_param(IS_OSPI_DQS_MODE (cmd->DQSMode));
927   assert_param(IS_OSPI_SIOO_MODE(cmd->SIOOMode));
928 
929   /* Check the state of the driver */
930   if ((hospi->State  == HAL_OSPI_STATE_READY) && (cmd->OperationType     == HAL_OSPI_OPTYPE_COMMON_CFG) &&
931       (cmd->DataMode == HAL_OSPI_DATA_NONE)   && (hospi->Init.MemoryType != HAL_OSPI_MEMTYPE_HYPERBUS))
932   {
933     /* Wait till busy flag is reset */
934     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
935 
936     if (status == HAL_OK)
937     {
938       /* Initialize error code */
939       hospi->ErrorCode = HAL_OSPI_ERROR_NONE;
940 
941       /* Clear flags related to interrupt */
942       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
943 
944       /* Configure the registers */
945       status = OSPI_ConfigCmd(hospi, cmd);
946 
947       if (status == HAL_OK)
948       {
949         /* Update the state */
950           hospi->State = HAL_OSPI_STATE_BUSY_CMD;
951 
952         /* Enable the transfer complete and transfer error interrupts */
953         __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_TE);
954       }
955     }
956   }
957   else
958   {
959     status = HAL_ERROR;
960     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
961   }
962 
963   /* Return function status */
964   return status;
965 }
966 
967 /**
968   * @brief  Configure the Hyperbus parameters.
969   * @param  hospi   : OSPI handle
970   * @param  cfg     : Structure containing the Hyperbus configuration
971   * @param  Timeout : Timeout duration
972   * @retval HAL status
973   */
HAL_OSPI_HyperbusCfg(OSPI_HandleTypeDef * hospi,OSPI_HyperbusCfgTypeDef * cfg,uint32_t Timeout)974 HAL_StatusTypeDef HAL_OSPI_HyperbusCfg(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCfgTypeDef *cfg, uint32_t Timeout)
975 {
976   HAL_StatusTypeDef status;
977   uint32_t state;
978   uint32_t tickstart = HAL_GetTick();
979 
980   /* Check the parameters of the hyperbus configuration structure */
981   assert_param(IS_OSPI_RW_RECOVERY_TIME  (cfg->RWRecoveryTime));
982   assert_param(IS_OSPI_ACCESS_TIME       (cfg->AccessTime));
983   assert_param(IS_OSPI_WRITE_ZERO_LATENCY(cfg->WriteZeroLatency));
984   assert_param(IS_OSPI_LATENCY_MODE      (cfg->LatencyMode));
985 
986   /* Check the state of the driver */
987   state = hospi->State;
988   if ((state == HAL_OSPI_STATE_HYPERBUS_INIT) || (state == HAL_OSPI_STATE_READY))
989   {
990     /* Wait till busy flag is reset */
991     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
992 
993     if (status == HAL_OK)
994     {
995       /* Configure Hyperbus configuration Latency register */
996       WRITE_REG(hospi->Instance->HLCR, ((cfg->RWRecoveryTime << OCTOSPI_HLCR_TRWR_Pos) |
997                                         (cfg->AccessTime << OCTOSPI_HLCR_TACC_Pos)     |
998                                         cfg->WriteZeroLatency | cfg->LatencyMode));
999 
1000       /* Update the state */
1001       hospi->State = HAL_OSPI_STATE_READY;
1002     }
1003   }
1004   else
1005   {
1006     status = HAL_ERROR;
1007     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1008   }
1009 
1010   /* Return function status */
1011   return status;
1012 }
1013 
1014 /**
1015   * @brief  Set the Hyperbus command configuration.
1016   * @param  hospi   : OSPI handle
1017   * @param  cmd     : Structure containing the Hyperbus command
1018   * @param  Timeout : Timeout duration
1019   * @retval HAL status
1020   */
HAL_OSPI_HyperbusCmd(OSPI_HandleTypeDef * hospi,OSPI_HyperbusCmdTypeDef * cmd,uint32_t Timeout)1021 HAL_StatusTypeDef HAL_OSPI_HyperbusCmd(OSPI_HandleTypeDef *hospi, OSPI_HyperbusCmdTypeDef *cmd, uint32_t Timeout)
1022 {
1023   HAL_StatusTypeDef status;
1024   uint32_t tickstart = HAL_GetTick();
1025 
1026   /* Check the parameters of the hyperbus command structure */
1027   assert_param(IS_OSPI_ADDRESS_SPACE(cmd->AddressSpace));
1028   assert_param(IS_OSPI_ADDRESS_SIZE (cmd->AddressSize));
1029   assert_param(IS_OSPI_NUMBER_DATA  (cmd->NbData));
1030   assert_param(IS_OSPI_DQS_MODE     (cmd->DQSMode));
1031 
1032   /* Check the state of the driver */
1033   if ((hospi->State == HAL_OSPI_STATE_READY) && (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS))
1034   {
1035     /* Wait till busy flag is reset */
1036     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
1037 
1038     if (status == HAL_OK)
1039     {
1040       /* Re-initialize the value of the functional mode */
1041       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U);
1042 
1043       /* Configure the address space in the DCR1 register */
1044       MODIFY_REG(hospi->Instance->DCR1, OCTOSPI_DCR1_MTYP_0, cmd->AddressSpace);
1045 
1046       /* Configure the CCR and WCCR registers with the address size and the following configuration :
1047          - DQS signal enabled (used as RWDS)
1048          - DTR mode enabled on address and data
1049          - address and data on 8 lines */
1050       WRITE_REG(hospi->Instance->CCR, (cmd->DQSMode | OCTOSPI_CCR_DDTR | OCTOSPI_CCR_DMODE_2 |
1051                                        cmd->AddressSize | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADMODE_2));
1052       WRITE_REG(hospi->Instance->WCCR, (cmd->DQSMode | OCTOSPI_WCCR_DDTR | OCTOSPI_WCCR_DMODE_2 |
1053                                         cmd->AddressSize | OCTOSPI_WCCR_ADDTR | OCTOSPI_WCCR_ADMODE_2));
1054 
1055       /* Configure the DLR register with the number of data */
1056       WRITE_REG(hospi->Instance->DLR, (cmd->NbData - 1U));
1057 
1058       /* Configure the AR register with the address value */
1059       WRITE_REG(hospi->Instance->AR, cmd->Address);
1060 
1061       /* Update the state */
1062       hospi->State = HAL_OSPI_STATE_CMD_CFG;
1063     }
1064   }
1065   else
1066   {
1067     status = HAL_ERROR;
1068     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1069   }
1070 
1071   /* Return function status */
1072   return status;
1073 }
1074 
1075 /**
1076   * @brief  Transmit an amount of data in blocking mode.
1077   * @param  hospi   : OSPI handle
1078   * @param  pData   : pointer to data buffer
1079   * @param  Timeout : Timeout duration
1080   * @note   This function is used only in Indirect Write Mode
1081   * @retval HAL status
1082   */
HAL_OSPI_Transmit(OSPI_HandleTypeDef * hospi,uint8_t * pData,uint32_t Timeout)1083 HAL_StatusTypeDef HAL_OSPI_Transmit(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout)
1084 {
1085   HAL_StatusTypeDef status;
1086   uint32_t tickstart = HAL_GetTick();
1087   __IO uint32_t *data_reg = &hospi->Instance->DR;
1088 
1089   /* Check the data pointer allocation */
1090   if (pData == NULL)
1091   {
1092     status = HAL_ERROR;
1093     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1094   }
1095   else
1096   {
1097     /* Check the state */
1098     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1099     {
1100       /* Configure counters and size */
1101       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1102       hospi->XferSize  = hospi->XferCount;
1103       hospi->pBuffPtr  = pData;
1104 
1105       /* Configure CR register with functional mode as indirect write */
1106       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
1107 
1108       do
1109       {
1110         /* Wait till fifo threshold flag is set to send data */
1111         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_FT, SET, tickstart, Timeout);
1112 
1113         if (status != HAL_OK)
1114         {
1115           break;
1116         }
1117 
1118         *((__IO uint8_t *)data_reg) = *hospi->pBuffPtr;
1119         hospi->pBuffPtr++;
1120         hospi->XferCount--;
1121       } while (hospi->XferCount > 0U);
1122 
1123       if (status == HAL_OK)
1124       {
1125         /* Wait till transfer complete flag is set to go back in idle state */
1126         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
1127 
1128         if (status == HAL_OK)
1129         {
1130           /* Clear transfer complete flag */
1131           __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
1132 
1133           /* Update state */
1134           hospi->State = HAL_OSPI_STATE_READY;
1135         }
1136       }
1137     }
1138     else
1139     {
1140       status = HAL_ERROR;
1141       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1142     }
1143   }
1144 
1145   /* Return function status */
1146   return status;
1147 }
1148 
1149 /**
1150   * @brief  Receive an amount of data in blocking mode.
1151   * @param  hospi   : OSPI handle
1152   * @param  pData   : pointer to data buffer
1153   * @param  Timeout : Timeout duration
1154   * @note   This function is used only in Indirect Read Mode
1155   * @retval HAL status
1156   */
HAL_OSPI_Receive(OSPI_HandleTypeDef * hospi,uint8_t * pData,uint32_t Timeout)1157 HAL_StatusTypeDef HAL_OSPI_Receive(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout)
1158 {
1159   HAL_StatusTypeDef status;
1160   uint32_t tickstart = HAL_GetTick();
1161   __IO uint32_t *data_reg = &hospi->Instance->DR;
1162   uint32_t addr_reg = hospi->Instance->AR;
1163   uint32_t ir_reg = hospi->Instance->IR;
1164 
1165   /* Check the data pointer allocation */
1166   if (pData == NULL)
1167   {
1168     status = HAL_ERROR;
1169     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1170   }
1171   else
1172   {
1173     /* Check the state */
1174     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1175     {
1176       /* Configure counters and size */
1177       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1178       hospi->XferSize  = hospi->XferCount;
1179       hospi->pBuffPtr  = pData;
1180 
1181       /* Configure CR register with functional mode as indirect read */
1182       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1183 
1184       /* Trig the transfer by re-writing address or instruction register */
1185       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1186       {
1187         WRITE_REG(hospi->Instance->AR, addr_reg);
1188       }
1189       else
1190       {
1191         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1192         {
1193           WRITE_REG(hospi->Instance->AR, addr_reg);
1194         }
1195         else
1196         {
1197           WRITE_REG(hospi->Instance->IR, ir_reg);
1198         }
1199       }
1200 
1201       do
1202       {
1203         /* Wait till fifo threshold or transfer complete flags are set to read received data */
1204         status = OSPI_WaitFlagStateUntilTimeout(hospi, (HAL_OSPI_FLAG_FT | HAL_OSPI_FLAG_TC), SET, tickstart, Timeout);
1205 
1206         if (status != HAL_OK)
1207         {
1208           break;
1209         }
1210 
1211         *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
1212         hospi->pBuffPtr++;
1213         hospi->XferCount--;
1214       } while(hospi->XferCount > 0U);
1215 
1216       if (status == HAL_OK)
1217       {
1218         /* Wait till transfer complete flag is set to go back in idle state */
1219         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
1220 
1221         if (status == HAL_OK)
1222         {
1223           /* Clear transfer complete flag */
1224           __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
1225 
1226           /* Update state */
1227           hospi->State = HAL_OSPI_STATE_READY;
1228         }
1229       }
1230     }
1231     else
1232     {
1233       status = HAL_ERROR;
1234       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1235     }
1236   }
1237 
1238   /* Return function status */
1239   return status;
1240 }
1241 
1242 /**
1243   * @brief  Send an amount of data in non-blocking mode with interrupt.
1244   * @param  hospi : OSPI handle
1245   * @param  pData : pointer to data buffer
1246   * @note   This function is used only in Indirect Write Mode
1247   * @retval HAL status
1248   */
HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef * hospi,uint8_t * pData)1249 HAL_StatusTypeDef HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1250 {
1251   HAL_StatusTypeDef status = HAL_OK;
1252 
1253   /* Check the data pointer allocation */
1254   if (pData == NULL)
1255   {
1256     status = HAL_ERROR;
1257     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1258   }
1259   else
1260   {
1261     /* Check the state */
1262     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1263     {
1264       /* Configure counters and size */
1265       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1266       hospi->XferSize  = hospi->XferCount;
1267       hospi->pBuffPtr  = pData;
1268 
1269       /* Configure CR register with functional mode as indirect write */
1270       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
1271 
1272       /* Clear flags related to interrupt */
1273       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1274 
1275       /* Update the state */
1276       hospi->State = HAL_OSPI_STATE_BUSY_TX;
1277 
1278       /* Enable the transfer complete, fifo threshold and transfer error interrupts */
1279       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
1280     }
1281     else
1282     {
1283       status = HAL_ERROR;
1284       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1285     }
1286   }
1287 
1288   /* Return function status */
1289   return status;
1290 }
1291 
1292 /**
1293   * @brief  Receive an amount of data in non-blocking mode with interrupt.
1294   * @param  hospi : OSPI handle
1295   * @param  pData : pointer to data buffer
1296   * @note   This function is used only in Indirect Read Mode
1297   * @retval HAL status
1298   */
HAL_OSPI_Receive_IT(OSPI_HandleTypeDef * hospi,uint8_t * pData)1299 HAL_StatusTypeDef HAL_OSPI_Receive_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1300 {
1301   HAL_StatusTypeDef status = HAL_OK;
1302   uint32_t addr_reg = hospi->Instance->AR;
1303   uint32_t ir_reg = hospi->Instance->IR;
1304 
1305   /* Check the data pointer allocation */
1306   if (pData == NULL)
1307   {
1308     status = HAL_ERROR;
1309     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1310   }
1311   else
1312   {
1313     /* Check the state */
1314     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1315     {
1316       /* Configure counters and size */
1317       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1318       hospi->XferSize  = hospi->XferCount;
1319       hospi->pBuffPtr  = pData;
1320 
1321       /* Configure CR register with functional mode as indirect read */
1322       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1323 
1324       /* Clear flags related to interrupt */
1325       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1326 
1327       /* Update the state */
1328       hospi->State = HAL_OSPI_STATE_BUSY_RX;
1329 
1330       /* Enable the transfer complete, fifo threshold and transfer error interrupts */
1331       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
1332 
1333       /* Trig the transfer by re-writing address or instruction register */
1334       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1335       {
1336         WRITE_REG(hospi->Instance->AR, addr_reg);
1337       }
1338       else
1339       {
1340         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1341         {
1342           WRITE_REG(hospi->Instance->AR, addr_reg);
1343         }
1344         else
1345         {
1346           WRITE_REG(hospi->Instance->IR, ir_reg);
1347         }
1348       }
1349     }
1350     else
1351     {
1352       status = HAL_ERROR;
1353       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1354     }
1355   }
1356 
1357   /* Return function status */
1358   return status;
1359 }
1360 
1361 /**
1362   * @brief  Send an amount of data in non-blocking mode with DMA.
1363   * @param  hospi : OSPI handle
1364   * @param  pData : pointer to data buffer
1365   * @note   This function is used only in Indirect Write Mode
1366   * @note   If DMA peripheral access is configured as halfword, the number
1367   *         of data and the fifo threshold should be aligned on halfword
1368   * @note   If DMA peripheral access is configured as word, the number
1369   *         of data and the fifo threshold should be aligned on word
1370   * @retval HAL status
1371   */
HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef * hospi,uint8_t * pData)1372 HAL_StatusTypeDef HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1373 {
1374   HAL_StatusTypeDef status = HAL_OK;
1375   uint32_t data_size = hospi->Instance->DLR + 1U;
1376 
1377   /* Check the data pointer allocation */
1378   if (pData == NULL)
1379   {
1380     status = HAL_ERROR;
1381     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1382   }
1383   else
1384   {
1385     /* Check the state */
1386     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1387     {
1388       /* Configure counters and size */
1389       if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
1390       {
1391         hospi->XferCount = data_size;
1392       }
1393       else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD)
1394       {
1395         if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U))
1396         {
1397           /* The number of data or the fifo threshold is not aligned on halfword
1398           => no transfer possible with DMA peripheral access configured as halfword */
1399           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1400           status = HAL_ERROR;
1401         }
1402         else
1403         {
1404           hospi->XferCount = (data_size >> 1);
1405         }
1406       }
1407       else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD)
1408       {
1409         if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U))
1410         {
1411           /* The number of data or the fifo threshold is not aligned on word
1412           => no transfer possible with DMA peripheral access configured as word */
1413           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1414           status = HAL_ERROR;
1415         }
1416         else
1417         {
1418           hospi->XferCount = (data_size >> 2);
1419         }
1420       }
1421       else
1422       {
1423         /* Nothing to do */
1424       }
1425 
1426       if (status == HAL_OK)
1427       {
1428         hospi->XferSize = hospi->XferCount;
1429         hospi->pBuffPtr = pData;
1430 
1431         /* Configure CR register with functional mode as indirect write */
1432         MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
1433 
1434         /* Clear flags related to interrupt */
1435         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1436 
1437         /* Update the state */
1438         hospi->State = HAL_OSPI_STATE_BUSY_TX;
1439 
1440         /* Set the DMA transfer complete callback */
1441         hospi->hdma->XferCpltCallback = OSPI_DMACplt;
1442 
1443         /* Set the DMA Half transfer complete callback */
1444         hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt;
1445 
1446         /* Set the DMA error callback */
1447         hospi->hdma->XferErrorCallback = OSPI_DMAError;
1448 
1449         /* Clear the DMA abort callback */
1450         hospi->hdma->XferAbortCallback = NULL;
1451 
1452         /* Configure the direction of the DMA */
1453         hospi->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH;
1454         MODIFY_REG(hospi->hdma->Instance->CCR, DMA_CCR_DIR, hospi->hdma->Init.Direction);
1455 
1456         /* Enable the transmit DMA Channel */
1457         if (HAL_DMA_Start_IT(hospi->hdma, (uint32_t)pData, (uint32_t)&hospi->Instance->DR, hospi->XferSize) == HAL_OK)
1458         {
1459           /* Enable the transfer error interrupt */
1460           __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
1461 
1462           /* Enable the DMA transfer by setting the DMAEN bit  */
1463           SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
1464         }
1465         else
1466         {
1467           status = HAL_ERROR;
1468           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1469           hospi->State = HAL_OSPI_STATE_READY;
1470         }
1471       }
1472     }
1473     else
1474     {
1475       status = HAL_ERROR;
1476       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1477     }
1478   }
1479 
1480   /* Return function status */
1481   return status;
1482 }
1483 
1484 /**
1485   * @brief  Receive an amount of data in non-blocking mode with DMA.
1486   * @param  hospi : OSPI handle
1487   * @param  pData : pointer to data buffer.
1488   * @note   This function is used only in Indirect Read Mode
1489   * @note   If DMA peripheral access is configured as halfword, the number
1490   *         of data and the fifo threshold should be aligned on halfword
1491   * @note   If DMA peripheral access is configured as word, the number
1492   *         of data and the fifo threshold should be aligned on word
1493   * @retval HAL status
1494   */
HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef * hospi,uint8_t * pData)1495 HAL_StatusTypeDef HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1496 {
1497   HAL_StatusTypeDef status = HAL_OK;
1498   uint32_t data_size = hospi->Instance->DLR + 1U;
1499   uint32_t addr_reg = hospi->Instance->AR;
1500   uint32_t ir_reg = hospi->Instance->IR;
1501 
1502   /* Check the data pointer allocation */
1503   if (pData == NULL)
1504   {
1505     status = HAL_ERROR;
1506     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1507   }
1508   else
1509   {
1510     /* Check the state */
1511     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1512     {
1513       /* Configure counters and size */
1514       if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_BYTE)
1515       {
1516         hospi->XferCount = data_size;
1517       }
1518       else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_HALFWORD)
1519       {
1520         if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U))
1521         {
1522           /* The number of data or the fifo threshold is not aligned on halfword
1523           => no transfer possible with DMA peripheral access configured as halfword */
1524           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1525           status = HAL_ERROR;
1526         }
1527         else
1528         {
1529           hospi->XferCount = (data_size >> 1);
1530         }
1531       }
1532       else if (hospi->hdma->Init.PeriphDataAlignment == DMA_PDATAALIGN_WORD)
1533       {
1534         if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U))
1535         {
1536           /* The number of data or the fifo threshold is not aligned on word
1537           => no transfer possible with DMA peripheral access configured as word */
1538           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1539           status = HAL_ERROR;
1540         }
1541         else
1542         {
1543           hospi->XferCount = (data_size >> 2);
1544         }
1545       }
1546       else
1547       {
1548         /* Nothing to do */
1549       }
1550 
1551       if (status == HAL_OK)
1552       {
1553         hospi->XferSize  = hospi->XferCount;
1554         hospi->pBuffPtr  = pData;
1555 
1556         /* Configure CR register with functional mode as indirect read */
1557         MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1558 
1559         /* Clear flags related to interrupt */
1560         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1561 
1562         /* Update the state */
1563         hospi->State = HAL_OSPI_STATE_BUSY_RX;
1564 
1565         /* Set the DMA transfer complete callback */
1566         hospi->hdma->XferCpltCallback = OSPI_DMACplt;
1567 
1568         /* Set the DMA Half transfer complete callback */
1569         hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt;
1570 
1571         /* Set the DMA error callback */
1572         hospi->hdma->XferErrorCallback = OSPI_DMAError;
1573 
1574         /* Clear the DMA abort callback */
1575         hospi->hdma->XferAbortCallback = NULL;
1576 
1577         /* Configure the direction of the DMA */
1578         hospi->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY;
1579         MODIFY_REG(hospi->hdma->Instance->CCR, DMA_CCR_DIR, hospi->hdma->Init.Direction);
1580 
1581         /* Enable the transmit DMA Channel */
1582         if (HAL_DMA_Start_IT(hospi->hdma, (uint32_t)&hospi->Instance->DR, (uint32_t)pData, hospi->XferSize) == HAL_OK)
1583         {
1584           /* Enable the transfer error interrupt */
1585           __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
1586 
1587           /* Trig the transfer by re-writing address or instruction register */
1588           if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1589           {
1590             WRITE_REG(hospi->Instance->AR, addr_reg);
1591           }
1592           else
1593           {
1594             if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1595             {
1596               WRITE_REG(hospi->Instance->AR, addr_reg);
1597             }
1598             else
1599             {
1600               WRITE_REG(hospi->Instance->IR, ir_reg);
1601             }
1602           }
1603 
1604           /* Enable the DMA transfer by setting the DMAEN bit  */
1605           SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
1606         }
1607         else
1608         {
1609           status = HAL_ERROR;
1610           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1611           hospi->State = HAL_OSPI_STATE_READY;
1612         }
1613       }
1614     }
1615     else
1616     {
1617       status = HAL_ERROR;
1618       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1619     }
1620   }
1621 
1622   /* Return function status */
1623   return status;
1624 }
1625 
1626 /**
1627   * @brief  Configure the OSPI Automatic Polling Mode in blocking mode.
1628   * @param  hospi   : OSPI handle
1629   * @param  cfg     : structure that contains the polling configuration information.
1630   * @param  Timeout : Timeout duration
1631   * @note   This function is used only in Automatic Polling Mode
1632   * @note   This function should not be used when the memory is in octal mode (see Errata Sheet)
1633   * @retval HAL status
1634   */
HAL_OSPI_AutoPolling(OSPI_HandleTypeDef * hospi,OSPI_AutoPollingTypeDef * cfg,uint32_t Timeout)1635 HAL_StatusTypeDef HAL_OSPI_AutoPolling(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
1636 {
1637   HAL_StatusTypeDef status;
1638   uint32_t tickstart = HAL_GetTick();
1639   uint32_t addr_reg = hospi->Instance->AR;
1640   uint32_t ir_reg = hospi->Instance->IR;
1641 #ifdef USE_FULL_ASSERT
1642   uint32_t dlr_reg = hospi->Instance->DLR;
1643 #endif
1644 
1645   /* Check the parameters of the autopolling configuration structure */
1646   assert_param(IS_OSPI_MATCH_MODE       (cfg->MatchMode));
1647   assert_param(IS_OSPI_AUTOMATIC_STOP   (cfg->AutomaticStop));
1648   assert_param(IS_OSPI_INTERVAL         (cfg->Interval));
1649   assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U));
1650 
1651   /* Check the state */
1652   if ((hospi->State == HAL_OSPI_STATE_CMD_CFG) && (cfg->AutomaticStop == HAL_OSPI_AUTOMATIC_STOP_ENABLE))
1653   {
1654     /* Wait till busy flag is reset */
1655     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
1656 
1657     if (status == HAL_OK)
1658     {
1659       /* Configure registers */
1660       WRITE_REG (hospi->Instance->PSMAR, cfg->Match);
1661       WRITE_REG (hospi->Instance->PSMKR, cfg->Mask);
1662       WRITE_REG (hospi->Instance->PIR,   cfg->Interval);
1663       MODIFY_REG(hospi->Instance->CR,    (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
1664                  (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
1665 
1666       /* Trig the transfer by re-writing address or instruction register */
1667       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1668       {
1669         WRITE_REG(hospi->Instance->AR, addr_reg);
1670       }
1671       else
1672       {
1673         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1674         {
1675           WRITE_REG(hospi->Instance->AR, addr_reg);
1676         }
1677         else
1678         {
1679           WRITE_REG(hospi->Instance->IR, ir_reg);
1680         }
1681       }
1682 
1683       /* Wait till status match flag is set to go back in idle state */
1684       status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout);
1685 
1686       if (status == HAL_OK)
1687       {
1688         /* Clear status match flag */
1689         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_SM);
1690 
1691         /* Update state */
1692         hospi->State = HAL_OSPI_STATE_READY;
1693       }
1694     }
1695   }
1696   else
1697   {
1698     status = HAL_ERROR;
1699     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1700   }
1701 
1702   /* Return function status */
1703   return status;
1704 }
1705 
1706 /**
1707   * @brief  Configure the OSPI Automatic Polling Mode in non-blocking mode.
1708   * @param  hospi : OSPI handle
1709   * @param  cfg   : structure that contains the polling configuration information.
1710   * @note   This function is used only in Automatic Polling Mode
1711   * @note   This function should not be used when the memory is in octal mode (see Errata Sheet)
1712   * @retval HAL status
1713   */
HAL_OSPI_AutoPolling_IT(OSPI_HandleTypeDef * hospi,OSPI_AutoPollingTypeDef * cfg)1714 HAL_StatusTypeDef HAL_OSPI_AutoPolling_IT(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg)
1715 {
1716   HAL_StatusTypeDef status;
1717   uint32_t tickstart = HAL_GetTick();
1718   uint32_t addr_reg = hospi->Instance->AR;
1719   uint32_t ir_reg = hospi->Instance->IR;
1720 #ifdef USE_FULL_ASSERT
1721   uint32_t dlr_reg = hospi->Instance->DLR;
1722 #endif
1723 
1724   /* Check the parameters of the autopolling configuration structure */
1725   assert_param(IS_OSPI_MATCH_MODE       (cfg->MatchMode));
1726   assert_param(IS_OSPI_AUTOMATIC_STOP   (cfg->AutomaticStop));
1727   assert_param(IS_OSPI_INTERVAL         (cfg->Interval));
1728   assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg+1U));
1729 
1730   /* Check the state */
1731   if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1732   {
1733     /* Wait till busy flag is reset */
1734     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
1735 
1736     if (status == HAL_OK)
1737     {
1738       /* Configure registers */
1739       WRITE_REG (hospi->Instance->PSMAR, cfg->Match);
1740       WRITE_REG (hospi->Instance->PSMKR, cfg->Mask);
1741       WRITE_REG (hospi->Instance->PIR,   cfg->Interval);
1742       MODIFY_REG(hospi->Instance->CR,    (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
1743                  (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
1744 
1745       /* Clear flags related to interrupt */
1746       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_SM);
1747 
1748       /* Update state */
1749       hospi->State = HAL_OSPI_STATE_BUSY_AUTO_POLLING;
1750 
1751       /* Enable the status match and transfer error interrupts */
1752       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE);
1753 
1754       /* Trig the transfer by re-writing address or instruction register */
1755       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1756       {
1757         WRITE_REG(hospi->Instance->AR, addr_reg);
1758       }
1759       else
1760       {
1761         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1762         {
1763           WRITE_REG(hospi->Instance->AR, addr_reg);
1764         }
1765         else
1766         {
1767           WRITE_REG(hospi->Instance->IR, ir_reg);
1768         }
1769       }
1770     }
1771   }
1772   else
1773   {
1774     status = HAL_ERROR;
1775     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1776   }
1777 
1778   /* Return function status */
1779   return status;
1780 }
1781 
1782 /**
1783   * @brief  Configure the Memory Mapped mode.
1784   * @param  hospi : OSPI handle
1785   * @param  cfg   : structure that contains the memory mapped configuration information.
1786   * @note   This function is used only in Memory mapped Mode
1787   * @retval HAL status
1788   */
HAL_OSPI_MemoryMapped(OSPI_HandleTypeDef * hospi,OSPI_MemoryMappedTypeDef * cfg)1789 HAL_StatusTypeDef HAL_OSPI_MemoryMapped(OSPI_HandleTypeDef *hospi, OSPI_MemoryMappedTypeDef *cfg)
1790 {
1791   HAL_StatusTypeDef status;
1792   uint32_t tickstart = HAL_GetTick();
1793 
1794   /* Check the parameters of the memory-mapped configuration structure */
1795   assert_param(IS_OSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation));
1796 
1797   /* Check the state */
1798   if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1799   {
1800     /* Wait till busy flag is reset */
1801     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
1802 
1803     if (status == HAL_OK)
1804     {
1805       /* Update state */
1806       hospi->State = HAL_OSPI_STATE_BUSY_MEM_MAPPED;
1807 
1808       if (cfg->TimeOutActivation == HAL_OSPI_TIMEOUT_COUNTER_ENABLE)
1809       {
1810         assert_param(IS_OSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod));
1811 
1812         /* Configure register */
1813         WRITE_REG(hospi->Instance->LPTR, cfg->TimeOutPeriod);
1814 
1815         /* Clear flags related to interrupt */
1816         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TO);
1817 
1818         /* Enable the timeout interrupt */
1819         __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TO);
1820       }
1821 
1822       /* Configure CR register with functional mode as memory-mapped */
1823       MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_TCEN | OCTOSPI_CR_FMODE),
1824                  (cfg->TimeOutActivation | OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED));
1825     }
1826   }
1827   else
1828   {
1829     status = HAL_ERROR;
1830     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1831   }
1832 
1833   /* Return function status */
1834   return status;
1835 }
1836 
1837 /**
1838   * @brief  Transfer Error callback.
1839   * @param  hospi : OSPI handle
1840   * @retval None
1841   */
HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef * hospi)1842 __weak void HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef *hospi)
1843 {
1844   /* Prevent unused argument(s) compilation warning */
1845   UNUSED(hospi);
1846 
1847   /* NOTE : This function should not be modified, when the callback is needed,
1848             the HAL_OSPI_ErrorCallback could be implemented in the user file
1849    */
1850 }
1851 
1852 /**
1853   * @brief  Abort completed callback.
1854   * @param  hospi : OSPI handle
1855   * @retval None
1856   */
HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef * hospi)1857 __weak void HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef *hospi)
1858 {
1859   /* Prevent unused argument(s) compilation warning */
1860   UNUSED(hospi);
1861 
1862   /* NOTE: This function should not be modified, when the callback is needed,
1863            the HAL_OSPI_AbortCpltCallback could be implemented in the user file
1864    */
1865 }
1866 
1867 /**
1868   * @brief  FIFO Threshold callback.
1869   * @param  hospi : OSPI handle
1870   * @retval None
1871   */
HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef * hospi)1872 __weak void HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef *hospi)
1873 {
1874   /* Prevent unused argument(s) compilation warning */
1875   UNUSED(hospi);
1876 
1877   /* NOTE : This function should not be modified, when the callback is needed,
1878             the HAL_OSPI_FIFOThresholdCallback could be implemented in the user file
1879    */
1880 }
1881 
1882 /**
1883   * @brief  Command completed callback.
1884   * @param  hospi : OSPI handle
1885   * @retval None
1886   */
HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef * hospi)1887 __weak void HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef *hospi)
1888 {
1889   /* Prevent unused argument(s) compilation warning */
1890   UNUSED(hospi);
1891 
1892   /* NOTE: This function should not be modified, when the callback is needed,
1893            the HAL_OSPI_CmdCpltCallback could be implemented in the user file
1894    */
1895 }
1896 
1897 /**
1898   * @brief  Rx Transfer completed callback.
1899   * @param  hospi : OSPI handle
1900   * @retval None
1901   */
HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef * hospi)1902 __weak void HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef *hospi)
1903 {
1904   /* Prevent unused argument(s) compilation warning */
1905   UNUSED(hospi);
1906 
1907   /* NOTE: This function should not be modified, when the callback is needed,
1908            the HAL_OSPI_RxCpltCallback could be implemented in the user file
1909    */
1910 }
1911 
1912 /**
1913   * @brief  Tx Transfer completed callback.
1914   * @param  hospi : OSPI handle
1915   * @retval None
1916   */
HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef * hospi)1917  __weak void HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef *hospi)
1918 {
1919   /* Prevent unused argument(s) compilation warning */
1920   UNUSED(hospi);
1921 
1922   /* NOTE: This function should not be modified, when the callback is needed,
1923            the HAL_OSPI_TxCpltCallback could be implemented in the user file
1924    */
1925 }
1926 
1927 /**
1928   * @brief  Rx Half Transfer completed callback.
1929   * @param  hospi : OSPI handle
1930   * @retval None
1931   */
HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef * hospi)1932 __weak void HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
1933 {
1934   /* Prevent unused argument(s) compilation warning */
1935   UNUSED(hospi);
1936 
1937   /* NOTE: This function should not be modified, when the callback is needed,
1938            the HAL_OSPI_RxHalfCpltCallback could be implemented in the user file
1939    */
1940 }
1941 
1942 /**
1943   * @brief  Tx Half Transfer completed callback.
1944   * @param  hospi : OSPI handle
1945   * @retval None
1946   */
HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef * hospi)1947 __weak void HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
1948 {
1949   /* Prevent unused argument(s) compilation warning */
1950   UNUSED(hospi);
1951 
1952   /* NOTE: This function should not be modified, when the callback is needed,
1953            the HAL_OSPI_TxHalfCpltCallback could be implemented in the user file
1954    */
1955 }
1956 
1957 /**
1958   * @brief  Status Match callback.
1959   * @param  hospi : OSPI handle
1960   * @retval None
1961   */
HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef * hospi)1962 __weak void HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef *hospi)
1963 {
1964   /* Prevent unused argument(s) compilation warning */
1965   UNUSED(hospi);
1966 
1967   /* NOTE : This function should not be modified, when the callback is needed,
1968             the HAL_OSPI_StatusMatchCallback could be implemented in the user file
1969    */
1970 }
1971 
1972 /**
1973   * @brief  Timeout callback.
1974   * @param  hospi : OSPI handle
1975   * @retval None
1976   */
HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef * hospi)1977 __weak void HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef *hospi)
1978 {
1979   /* Prevent unused argument(s) compilation warning */
1980   UNUSED(hospi);
1981 
1982   /* NOTE : This function should not be modified, when the callback is needed,
1983             the HAL_OSPI_TimeOutCallback could be implemented in the user file
1984    */
1985 }
1986 
1987 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
1988 /**
1989   * @brief  Register a User OSPI Callback
1990   *         To be used instead of the weak (surcharged) predefined callback
1991   * @param hospi : OSPI handle
1992   * @param CallbackID : ID of the callback to be registered
1993   *        This parameter can be one of the following values:
1994   *          @arg @ref HAL_OSPI_ERROR_CB_ID          OSPI Error Callback ID
1995   *          @arg @ref HAL_OSPI_ABORT_CB_ID          OSPI Abort Callback ID
1996   *          @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
1997   *          @arg @ref HAL_OSPI_CMD_CPLT_CB_ID       OSPI Command Complete Callback ID
1998   *          @arg @ref HAL_OSPI_RX_CPLT_CB_ID        OSPI Rx Complete Callback ID
1999   *          @arg @ref HAL_OSPI_TX_CPLT_CB_ID        OSPI Tx Complete Callback ID
2000   *          @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID   OSPI Rx Half Complete Callback ID
2001   *          @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID   OSPI Tx Half Complete Callback ID
2002   *          @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID   OSPI Status Match Callback ID
2003   *          @arg @ref HAL_OSPI_TIMEOUT_CB_ID        OSPI Timeout Callback ID
2004   *          @arg @ref HAL_OSPI_MSP_INIT_CB_ID       OSPI MspInit callback ID
2005   *          @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID     OSPI MspDeInit callback ID
2006   * @param pCallback : pointer to the Callback function
2007   * @retval status
2008   */
HAL_OSPI_RegisterCallback(OSPI_HandleTypeDef * hospi,HAL_OSPI_CallbackIDTypeDef CallbackID,pOSPI_CallbackTypeDef pCallback)2009 HAL_StatusTypeDef HAL_OSPI_RegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID, pOSPI_CallbackTypeDef pCallback)
2010 {
2011   HAL_StatusTypeDef status = HAL_OK;
2012 
2013   if(pCallback == NULL)
2014   {
2015     /* Update the error code */
2016     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2017     return HAL_ERROR;
2018   }
2019 
2020   if(hospi->State == HAL_OSPI_STATE_READY)
2021   {
2022     switch (CallbackID)
2023     {
2024     case  HAL_OSPI_ERROR_CB_ID :
2025       hospi->ErrorCallback = pCallback;
2026       break;
2027     case HAL_OSPI_ABORT_CB_ID :
2028       hospi->AbortCpltCallback = pCallback;
2029       break;
2030     case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
2031       hospi->FifoThresholdCallback = pCallback;
2032       break;
2033     case HAL_OSPI_CMD_CPLT_CB_ID :
2034       hospi->CmdCpltCallback = pCallback;
2035       break;
2036     case HAL_OSPI_RX_CPLT_CB_ID :
2037       hospi->RxCpltCallback = pCallback;
2038       break;
2039     case HAL_OSPI_TX_CPLT_CB_ID :
2040       hospi->TxCpltCallback = pCallback;
2041       break;
2042     case HAL_OSPI_RX_HALF_CPLT_CB_ID :
2043       hospi->RxHalfCpltCallback = pCallback;
2044       break;
2045     case HAL_OSPI_TX_HALF_CPLT_CB_ID :
2046       hospi->TxHalfCpltCallback = pCallback;
2047       break;
2048     case HAL_OSPI_STATUS_MATCH_CB_ID :
2049       hospi->StatusMatchCallback = pCallback;
2050       break;
2051     case HAL_OSPI_TIMEOUT_CB_ID :
2052       hospi->TimeOutCallback = pCallback;
2053       break;
2054     case HAL_OSPI_MSP_INIT_CB_ID :
2055       hospi->MspInitCallback = pCallback;
2056       break;
2057     case HAL_OSPI_MSP_DEINIT_CB_ID :
2058       hospi->MspDeInitCallback = pCallback;
2059       break;
2060     default :
2061       /* Update the error code */
2062       hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2063       /* update return status */
2064       status =  HAL_ERROR;
2065       break;
2066     }
2067   }
2068   else if (hospi->State == HAL_OSPI_STATE_RESET)
2069   {
2070     switch (CallbackID)
2071     {
2072     case HAL_OSPI_MSP_INIT_CB_ID :
2073       hospi->MspInitCallback = pCallback;
2074       break;
2075     case HAL_OSPI_MSP_DEINIT_CB_ID :
2076       hospi->MspDeInitCallback = pCallback;
2077       break;
2078     default :
2079       /* Update the error code */
2080       hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2081       /* update return status */
2082       status =  HAL_ERROR;
2083       break;
2084     }
2085   }
2086   else
2087   {
2088     /* Update the error code */
2089     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2090     /* update return status */
2091     status =  HAL_ERROR;
2092   }
2093 
2094   return status;
2095 }
2096 
2097 /**
2098   * @brief  Unregister a User OSPI Callback
2099   *         OSPI Callback is redirected to the weak (surcharged) predefined callback
2100   * @param hospi : OSPI handle
2101   * @param CallbackID : ID of the callback to be unregistered
2102   *        This parameter can be one of the following values:
2103   *          @arg @ref HAL_OSPI_ERROR_CB_ID          OSPI Error Callback ID
2104   *          @arg @ref HAL_OSPI_ABORT_CB_ID          OSPI Abort Callback ID
2105   *          @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
2106   *          @arg @ref HAL_OSPI_CMD_CPLT_CB_ID       OSPI Command Complete Callback ID
2107   *          @arg @ref HAL_OSPI_RX_CPLT_CB_ID        OSPI Rx Complete Callback ID
2108   *          @arg @ref HAL_OSPI_TX_CPLT_CB_ID        OSPI Tx Complete Callback ID
2109   *          @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID   OSPI Rx Half Complete Callback ID
2110   *          @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID   OSPI Tx Half Complete Callback ID
2111   *          @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID   OSPI Status Match Callback ID
2112   *          @arg @ref HAL_OSPI_TIMEOUT_CB_ID        OSPI Timeout Callback ID
2113   *          @arg @ref HAL_OSPI_MSP_INIT_CB_ID       OSPI MspInit callback ID
2114   *          @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID     OSPI MspDeInit callback ID
2115   * @retval status
2116   */
HAL_OSPI_UnRegisterCallback(OSPI_HandleTypeDef * hospi,HAL_OSPI_CallbackIDTypeDef CallbackID)2117 HAL_StatusTypeDef HAL_OSPI_UnRegisterCallback (OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID)
2118 {
2119   HAL_StatusTypeDef status = HAL_OK;
2120 
2121   if(hospi->State == HAL_OSPI_STATE_READY)
2122   {
2123     switch (CallbackID)
2124     {
2125     case  HAL_OSPI_ERROR_CB_ID :
2126       hospi->ErrorCallback = HAL_OSPI_ErrorCallback;
2127       break;
2128     case HAL_OSPI_ABORT_CB_ID :
2129       hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback;
2130       break;
2131     case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
2132       hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback;
2133       break;
2134     case HAL_OSPI_CMD_CPLT_CB_ID :
2135       hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback;
2136       break;
2137     case HAL_OSPI_RX_CPLT_CB_ID :
2138       hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback;
2139       break;
2140     case HAL_OSPI_TX_CPLT_CB_ID :
2141       hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback;
2142       break;
2143     case HAL_OSPI_RX_HALF_CPLT_CB_ID :
2144       hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback;
2145       break;
2146     case HAL_OSPI_TX_HALF_CPLT_CB_ID :
2147       hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback;
2148       break;
2149     case HAL_OSPI_STATUS_MATCH_CB_ID :
2150       hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback;
2151       break;
2152     case HAL_OSPI_TIMEOUT_CB_ID :
2153       hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback;
2154       break;
2155     case HAL_OSPI_MSP_INIT_CB_ID :
2156       hospi->MspInitCallback = HAL_OSPI_MspInit;
2157       break;
2158     case HAL_OSPI_MSP_DEINIT_CB_ID :
2159       hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
2160       break;
2161     default :
2162       /* Update the error code */
2163       hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2164       /* update return status */
2165       status =  HAL_ERROR;
2166       break;
2167     }
2168   }
2169   else if (hospi->State == HAL_OSPI_STATE_RESET)
2170   {
2171     switch (CallbackID)
2172     {
2173     case HAL_OSPI_MSP_INIT_CB_ID :
2174       hospi->MspInitCallback = HAL_OSPI_MspInit;
2175       break;
2176     case HAL_OSPI_MSP_DEINIT_CB_ID :
2177       hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
2178       break;
2179     default :
2180       /* Update the error code */
2181       hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2182       /* update return status */
2183       status =  HAL_ERROR;
2184       break;
2185     }
2186   }
2187   else
2188   {
2189     /* Update the error code */
2190     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2191     /* update return status */
2192     status =  HAL_ERROR;
2193   }
2194 
2195   return status;
2196 }
2197 #endif
2198 
2199 /**
2200   * @}
2201   */
2202 
2203 /** @defgroup OSPI_Exported_Functions_Group3 Peripheral Control and State functions
2204   *  @brief   OSPI control and State functions
2205   *
2206 @verbatim
2207  ===============================================================================
2208                   ##### Peripheral Control and State functions #####
2209  ===============================================================================
2210     [..]
2211     This subsection provides a set of functions allowing to :
2212       (+) Check in run-time the state of the driver.
2213       (+) Check the error code set during last operation.
2214       (+) Abort any operation.
2215       (+) Manage the Fifo threshold.
2216       (+) Configure the timeout duration used in the driver.
2217 
2218 @endverbatim
2219   * @{
2220   */
2221 
2222 /**
2223 * @brief  Abort the current transmission.
2224 * @param  hospi : OSPI handle
2225 * @retval HAL status
2226 */
HAL_OSPI_Abort(OSPI_HandleTypeDef * hospi)2227 HAL_StatusTypeDef HAL_OSPI_Abort(OSPI_HandleTypeDef *hospi)
2228 {
2229   HAL_StatusTypeDef status = HAL_OK;
2230   uint32_t state;
2231   uint32_t tickstart = HAL_GetTick();
2232 
2233   /* Check if the state is in one of the busy or configured states */
2234   state = hospi->State;
2235   if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
2236   {
2237     /* Check if the DMA is enabled */
2238     if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
2239     {
2240       /* Disable the DMA transfer on the OctoSPI side */
2241       CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2242 
2243       /* Disable the DMA transfer on the DMA side */
2244       status = HAL_DMA_Abort(hospi->hdma);
2245       if (status != HAL_OK)
2246       {
2247         hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
2248       }
2249     }
2250 
2251     if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2252     {
2253       /* Perform an abort of the OctoSPI */
2254       SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2255 
2256       /* Wait until the transfer complete flag is set to go back in idle state */
2257       status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, hospi->Timeout);
2258 
2259       if (status == HAL_OK)
2260       {
2261         /* Clear transfer complete flag */
2262         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2263 
2264         /* Wait until the busy flag is reset to go back in idle state */
2265         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
2266 
2267         if (status == HAL_OK)
2268         {
2269           /* Update state */
2270           hospi->State = HAL_OSPI_STATE_READY;
2271         }
2272       }
2273     }
2274     else
2275     {
2276       /* Update state */
2277       hospi->State = HAL_OSPI_STATE_READY;
2278     }
2279   }
2280   else
2281   {
2282     status = HAL_ERROR;
2283     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2284   }
2285 
2286   /* Return function status */
2287   return status;
2288 }
2289 
2290 /**
2291 * @brief  Abort the current transmission (non-blocking function)
2292 * @param  hospi : OSPI handle
2293 * @retval HAL status
2294 */
HAL_OSPI_Abort_IT(OSPI_HandleTypeDef * hospi)2295 HAL_StatusTypeDef HAL_OSPI_Abort_IT(OSPI_HandleTypeDef *hospi)
2296 {
2297   HAL_StatusTypeDef status = HAL_OK;
2298   uint32_t state;
2299 
2300   /* Check if the state is in one of the busy or configured states */
2301   state = hospi->State;
2302   if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
2303   {
2304     /* Disable all interrupts */
2305     __HAL_OSPI_DISABLE_IT(hospi, (HAL_OSPI_IT_TO | HAL_OSPI_IT_SM | HAL_OSPI_IT_FT | HAL_OSPI_IT_TC | HAL_OSPI_IT_TE));
2306 
2307     /* Update state */
2308     hospi->State = HAL_OSPI_STATE_ABORT;
2309 
2310     /* Check if the DMA is enabled */
2311     if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
2312     {
2313       /* Disable the DMA transfer on the OctoSPI side */
2314       CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2315 
2316       /* Disable the DMA transfer on the DMA side */
2317       hospi->hdma->XferAbortCallback = OSPI_DMAAbortCplt;
2318       if (HAL_DMA_Abort_IT(hospi->hdma) != HAL_OK)
2319       {
2320         /* Update state */
2321         hospi->State = HAL_OSPI_STATE_READY;
2322 
2323         /* Abort callback */
2324 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2325         hospi->AbortCpltCallback(hospi);
2326 #else
2327         HAL_OSPI_AbortCpltCallback(hospi);
2328 #endif
2329       }
2330     }
2331     else
2332     {
2333       if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2334       {
2335         /* Clear transfer complete flag */
2336         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2337 
2338         /* Enable the transfer complete interrupts */
2339         __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2340 
2341         /* Perform an abort of the OctoSPI */
2342         SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2343       }
2344       else
2345       {
2346         /* Update state */
2347         hospi->State = HAL_OSPI_STATE_READY;
2348 
2349         /* Abort callback */
2350 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2351         hospi->AbortCpltCallback(hospi);
2352 #else
2353         HAL_OSPI_AbortCpltCallback(hospi);
2354 #endif
2355       }
2356     }
2357   }
2358   else
2359   {
2360     status = HAL_ERROR;
2361     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2362   }
2363 
2364   /* Return function status */
2365   return status;
2366 }
2367 
2368 /** @brief  Set OSPI Fifo threshold.
2369   * @param  hospi     : OSPI handle.
2370   * @param  Threshold : Threshold of the Fifo.
2371   * @retval HAL status
2372   */
HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef * hospi,uint32_t Threshold)2373 HAL_StatusTypeDef HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef *hospi, uint32_t Threshold)
2374 {
2375   HAL_StatusTypeDef status = HAL_OK;
2376 
2377   /* Check the state */
2378   if ((hospi->State & OSPI_BUSY_STATE_MASK) == 0U)
2379   {
2380     /* Synchronize initialization structure with the new fifo threshold value */
2381     hospi->Init.FifoThreshold = Threshold;
2382 
2383     /* Configure new fifo threshold */
2384     MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold-1U) << OCTOSPI_CR_FTHRES_Pos));
2385 
2386   }
2387   else
2388   {
2389     status = HAL_ERROR;
2390     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2391   }
2392 
2393   /* Return function status */
2394   return status;
2395 }
2396 
2397 /** @brief  Get OSPI Fifo threshold.
2398   * @param  hospi : OSPI handle.
2399   * @retval Fifo threshold
2400   */
HAL_OSPI_GetFifoThreshold(OSPI_HandleTypeDef * hospi)2401 uint32_t HAL_OSPI_GetFifoThreshold(OSPI_HandleTypeDef *hospi)
2402 {
2403   return ((READ_BIT(hospi->Instance->CR, OCTOSPI_CR_FTHRES) >> OCTOSPI_CR_FTHRES_Pos) + 1U);
2404 }
2405 
2406 /** @brief Set OSPI timeout.
2407   * @param  hospi   : OSPI handle.
2408   * @param  Timeout : Timeout for the memory access.
2409   * @retval None
2410   */
HAL_OSPI_SetTimeout(OSPI_HandleTypeDef * hospi,uint32_t Timeout)2411 HAL_StatusTypeDef HAL_OSPI_SetTimeout(OSPI_HandleTypeDef *hospi, uint32_t Timeout)
2412 {
2413   hospi->Timeout = Timeout;
2414   return HAL_OK;
2415 }
2416 
2417 /**
2418 * @brief  Return the OSPI error code.
2419 * @param  hospi : OSPI handle
2420 * @retval OSPI Error Code
2421 */
HAL_OSPI_GetError(OSPI_HandleTypeDef * hospi)2422 uint32_t HAL_OSPI_GetError(OSPI_HandleTypeDef *hospi)
2423 {
2424   return hospi->ErrorCode;
2425 }
2426 
2427 /**
2428   * @brief  Return the OSPI handle state.
2429   * @param  hospi : OSPI handle
2430   * @retval HAL state
2431   */
HAL_OSPI_GetState(OSPI_HandleTypeDef * hospi)2432 uint32_t HAL_OSPI_GetState(OSPI_HandleTypeDef *hospi)
2433 {
2434   /* Return OSPI handle state */
2435   return hospi->State;
2436 }
2437 
2438 /**
2439   * @}
2440   */
2441 
2442 /** @defgroup OSPI_Exported_Functions_Group4 IO Manager configuration function
2443   *  @brief   OSPI IO Manager configuration function
2444   *
2445 @verbatim
2446  ===============================================================================
2447                   ##### IO Manager configuration function #####
2448  ===============================================================================
2449     [..]
2450     This subsection provides a set of functions allowing to :
2451       (+) Configure the IO manager.
2452 
2453 @endverbatim
2454   * @{
2455   */
2456 
2457 /**
2458   * @brief  Configure the OctoSPI IO manager.
2459   * @param  hospi   : OSPI handle
2460   * @param  cfg     : Configuration of the IO Manager for the instance
2461   * @param  Timeout : Timeout duration
2462   * @retval HAL status
2463   */
HAL_OSPIM_Config(OSPI_HandleTypeDef * hospi,OSPIM_CfgTypeDef * cfg,uint32_t Timeout)2464 HAL_StatusTypeDef HAL_OSPIM_Config(OSPI_HandleTypeDef *hospi, OSPIM_CfgTypeDef *cfg, uint32_t Timeout)
2465 {
2466   HAL_StatusTypeDef status = HAL_OK;
2467   uint32_t instance;
2468   uint8_t index, ospi_enabled = 0U, other_instance;
2469   OSPIM_CfgTypeDef IOM_cfg[OSPI_NB_INSTANCE];
2470 
2471   /* Prevent unused argument(s) compilation warning */
2472   UNUSED(Timeout);
2473 
2474   /* Check the parameters of the OctoSPI IO Manager configuration structure */
2475   assert_param(IS_OSPIM_PORT(cfg->ClkPort));
2476   assert_param(IS_OSPIM_PORT(cfg->DQSPort));
2477   assert_param(IS_OSPIM_PORT(cfg->NCSPort));
2478   assert_param(IS_OSPIM_IO_PORT(cfg->IOLowPort));
2479   assert_param(IS_OSPIM_IO_PORT(cfg->IOHighPort));
2480 
2481   if (hospi->Instance == OCTOSPI1)
2482   {
2483     instance = 0U;
2484     other_instance = 1U;
2485   }
2486   else
2487   {
2488     instance = 1U;
2489     other_instance = 0U;
2490   }
2491 
2492   /**************** Get current configuration of the instances ****************/
2493   for (index = 0U; index < OSPI_NB_INSTANCE; index++)
2494   {
2495     if (OSPIM_GetConfig(index+1U, &(IOM_cfg[index])) != HAL_OK)
2496     {
2497       status = HAL_ERROR;
2498       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
2499     }
2500   }
2501 
2502   if (status == HAL_OK)
2503   {
2504     /********** Disable both OctoSPI to configure OctoSPI IO Manager **********/
2505     if ((OCTOSPI1->CR & OCTOSPI_CR_EN) != 0U)
2506     {
2507       CLEAR_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
2508       ospi_enabled |= 0x1U;
2509     }
2510     if ((OCTOSPI2->CR & OCTOSPI_CR_EN) != 0U)
2511     {
2512       CLEAR_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
2513       ospi_enabled |= 0x2U;
2514     }
2515 
2516     /***************** Deactivation of previous configuration *****************/
2517     if (IOM_cfg[instance].ClkPort != 0U)
2518     {
2519       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].ClkPort-1U)],                          OCTOSPIM_PCR_CLKEN);
2520       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].DQSPort-1U)],                          OCTOSPIM_PCR_DQSEN);
2521       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].NCSPort-1U)],                          OCTOSPIM_PCR_NCSEN);
2522       CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)],  OCTOSPIM_PCR_IOLEN);
2523       CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN);
2524     }
2525 
2526     /********************* Deactivation of other instance *********************/
2527     if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) || (cfg->DQSPort == IOM_cfg[other_instance].DQSPort)     ||
2528         (cfg->NCSPort == IOM_cfg[other_instance].NCSPort) || (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) ||
2529         (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort))
2530     {
2531       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort-1U)],                          OCTOSPIM_PCR_CLKEN);
2532       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort-1U)],                          OCTOSPIM_PCR_DQSEN);
2533       CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].NCSPort-1U)],                          OCTOSPIM_PCR_NCSEN);
2534       CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort-1U)& OSPI_IOM_PORT_MASK)],  OCTOSPIM_PCR_IOLEN);
2535       CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort-1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN);
2536     }
2537 
2538     /******************** Activation of new configuration *********************/
2539     MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort-1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), (OCTOSPIM_PCR_CLKEN | (instance << OCTOSPIM_PCR_CLKSRC_Pos)));
2540     MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort-1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), (OCTOSPIM_PCR_DQSEN | (instance << OCTOSPIM_PCR_DQSSRC_Pos)));
2541     MODIFY_REG(OCTOSPIM->PCR[(cfg->NCSPort-1U)], (OCTOSPIM_PCR_NCSEN | OCTOSPIM_PCR_NCSSRC), (OCTOSPIM_PCR_NCSEN | (instance << OCTOSPIM_PCR_NCSSRC_Pos)));
2542 
2543     if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U)
2544     {
2545       MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
2546                  (OCTOSPIM_PCR_IOLEN | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U))));
2547     }
2548     else
2549     {
2550       MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
2551                  (OCTOSPIM_PCR_IOHEN | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U))));
2552     }
2553 
2554     if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U)
2555     {
2556       MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
2557                  (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0 | (instance << (OCTOSPIM_PCR_IOLSRC_Pos+1U))));
2558     }
2559     else
2560     {
2561       MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort-1U)& OSPI_IOM_PORT_MASK)], (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
2562                  (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0 | (instance << (OCTOSPIM_PCR_IOHSRC_Pos+1U))));
2563     }
2564 
2565     /******* Re-enable both OctoSPI after configure OctoSPI IO Manager ********/
2566     if ((ospi_enabled & 0x1U) != 0U)
2567     {
2568       SET_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
2569     }
2570     if ((ospi_enabled & 0x2U) != 0U)
2571     {
2572       SET_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
2573     }
2574   }
2575 
2576   /* Return function status */
2577   return status;
2578 }
2579 
2580 /**
2581   * @}
2582   */
2583 
2584 /**
2585   @cond 0
2586   */
2587 /**
2588   * @brief  DMA OSPI process complete callback.
2589   * @param  hdma : DMA handle
2590   * @retval None
2591   */
OSPI_DMACplt(DMA_HandleTypeDef * hdma)2592 static void OSPI_DMACplt(DMA_HandleTypeDef *hdma)
2593 {
2594   OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent);
2595   hospi->XferCount = 0;
2596 
2597   /* Disable the DMA transfer on the OctoSPI side */
2598   CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2599 
2600   /* Disable the DMA channel */
2601   __HAL_DMA_DISABLE(hdma);
2602 
2603   /* Enable the OSPI transfer complete Interrupt */
2604   __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2605 }
2606 
2607 /**
2608   * @brief  DMA OSPI process half complete callback.
2609   * @param  hdma : DMA handle
2610   * @retval None
2611   */
OSPI_DMAHalfCplt(DMA_HandleTypeDef * hdma)2612 static void OSPI_DMAHalfCplt(DMA_HandleTypeDef *hdma)
2613 {
2614   OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent);
2615   hospi->XferCount = (hospi->XferCount >> 1);
2616 
2617   if (hospi->State == HAL_OSPI_STATE_BUSY_RX)
2618   {
2619 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2620     hospi->RxHalfCpltCallback(hospi);
2621 #else
2622     HAL_OSPI_RxHalfCpltCallback(hospi);
2623 #endif
2624   }
2625   else
2626   {
2627 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2628     hospi->TxHalfCpltCallback(hospi);
2629 #else
2630     HAL_OSPI_TxHalfCpltCallback(hospi);
2631 #endif
2632   }
2633 }
2634 
2635 /**
2636   * @brief  DMA OSPI communication error callback.
2637   * @param  hdma : DMA handle
2638   * @retval None
2639   */
OSPI_DMAError(DMA_HandleTypeDef * hdma)2640 static void OSPI_DMAError(DMA_HandleTypeDef *hdma)
2641 {
2642   OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent);
2643   hospi->XferCount = 0;
2644   hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
2645 
2646   /* Disable the DMA transfer on the OctoSPI side */
2647   CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2648 
2649   /* Abort the OctoSPI */
2650   if (HAL_OSPI_Abort_IT(hospi) != HAL_OK)
2651   {
2652     /* Disable the interrupts */
2653     __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
2654 
2655     /* Update state */
2656     hospi->State = HAL_OSPI_STATE_READY;
2657 
2658     /* Error callback */
2659 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2660     hospi->ErrorCallback(hospi);
2661 #else
2662     HAL_OSPI_ErrorCallback(hospi);
2663 #endif
2664   }
2665 }
2666 
2667 /**
2668   * @brief  DMA OSPI abort complete callback.
2669   * @param  hdma : DMA handle
2670   * @retval None
2671   */
OSPI_DMAAbortCplt(DMA_HandleTypeDef * hdma)2672 static void OSPI_DMAAbortCplt(DMA_HandleTypeDef *hdma)
2673 {
2674   OSPI_HandleTypeDef* hospi = ( OSPI_HandleTypeDef* )(hdma->Parent);
2675   hospi->XferCount = 0;
2676 
2677   /* Check the state */
2678   if (hospi->State == HAL_OSPI_STATE_ABORT)
2679   {
2680     /* DMA abort called by OctoSPI abort */
2681     if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2682     {
2683       /* Clear transfer complete flag */
2684       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2685 
2686       /* Enable the transfer complete interrupts */
2687       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2688 
2689       /* Perform an abort of the OctoSPI */
2690       SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2691     }
2692     else
2693     {
2694       /* Update state */
2695       hospi->State = HAL_OSPI_STATE_READY;
2696 
2697       /* Abort callback */
2698 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2699       hospi->AbortCpltCallback(hospi);
2700 #else
2701       HAL_OSPI_AbortCpltCallback(hospi);
2702 #endif
2703     }
2704   }
2705   else
2706   {
2707     /* DMA abort called due to a transfer error interrupt */
2708     /* Update state */
2709     hospi->State = HAL_OSPI_STATE_READY;
2710 
2711     /* Error callback */
2712 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2713     hospi->ErrorCallback(hospi);
2714 #else
2715     HAL_OSPI_ErrorCallback(hospi);
2716 #endif
2717   }
2718 }
2719 
2720 /**
2721   * @brief  Wait for a flag state until timeout.
2722   * @param  hospi     : OSPI handle
2723   * @param  Flag      : Flag checked
2724   * @param  State     : Value of the flag expected
2725   * @param  Timeout   : Duration of the timeout
2726   * @param  Tickstart : Tick start value
2727   * @retval HAL status
2728   */
OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef * hospi,uint32_t Flag,FlagStatus State,uint32_t Tickstart,uint32_t Timeout)2729 static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag,
2730                                                         FlagStatus State, uint32_t Tickstart, uint32_t Timeout)
2731 {
2732   /* Wait until flag is in expected state */
2733   while((__HAL_OSPI_GET_FLAG(hospi, Flag)) != State)
2734   {
2735     /* Check for the Timeout */
2736     if (Timeout != HAL_MAX_DELAY)
2737     {
2738       if(((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
2739       {
2740         hospi->State     = HAL_OSPI_STATE_ERROR;
2741         hospi->ErrorCode |= HAL_OSPI_ERROR_TIMEOUT;
2742 
2743         return HAL_ERROR;
2744       }
2745     }
2746   }
2747   return HAL_OK;
2748 }
2749 
2750 /**
2751   * @brief  Configure the registers for the regular command mode.
2752   * @param  hospi : OSPI handle
2753   * @param  cmd   : structure that contains the command configuration information
2754   * @retval HAL status
2755   */
OSPI_ConfigCmd(OSPI_HandleTypeDef * hospi,OSPI_RegularCmdTypeDef * cmd)2756 static HAL_StatusTypeDef OSPI_ConfigCmd(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd)
2757 {
2758   HAL_StatusTypeDef status = HAL_OK;
2759   __IO uint32_t *ccr_reg, *tcr_reg, *ir_reg, *abr_reg;
2760 
2761   /* Re-initialize the value of the functional mode */
2762   MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U);
2763 
2764   /* Configure the flash ID */
2765   if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
2766   {
2767     MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FSEL, cmd->FlashId);
2768   }
2769 
2770   if (cmd->OperationType != HAL_OSPI_OPTYPE_WRITE_CFG)
2771   {
2772     ccr_reg = &(hospi->Instance->CCR);
2773     tcr_reg = &(hospi->Instance->TCR);
2774     ir_reg  = &(hospi->Instance->IR);
2775     abr_reg = &(hospi->Instance->ABR);
2776   }
2777   else
2778   {
2779     ccr_reg = &(hospi->Instance->WCCR);
2780     tcr_reg = &(hospi->Instance->WTCR);
2781     ir_reg  = &(hospi->Instance->WIR);
2782     abr_reg = &(hospi->Instance->WABR);
2783   }
2784 
2785   /* Configure the CCR register with DQS and SIOO modes */
2786   *ccr_reg = (cmd->DQSMode | cmd->SIOOMode);
2787 
2788   if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
2789   {
2790     /* Configure the ABR register with alternate bytes value */
2791     *abr_reg = cmd->AlternateBytes;
2792 
2793     /* Configure the CCR register with alternate bytes communication parameters */
2794     MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ABMODE | OCTOSPI_CCR_ABDTR | OCTOSPI_CCR_ABSIZE),
2795                            (cmd->AlternateBytesMode | cmd->AlternateBytesDtrMode | cmd->AlternateBytesSize));
2796   }
2797 
2798   /* Configure the TCR register with the number of dummy cycles */
2799   MODIFY_REG((*tcr_reg), OCTOSPI_TCR_DCYC, cmd->DummyCycles);
2800 
2801   if (cmd->DataMode != HAL_OSPI_DATA_NONE)
2802   {
2803     if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
2804     {
2805       /* Configure the DLR register with the number of data */
2806       hospi->Instance->DLR = (cmd->NbData - 1U);
2807     }
2808   }
2809 
2810   if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
2811   {
2812     if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
2813     {
2814       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
2815       {
2816         /* ---- Command with instruction, address and data ---- */
2817 
2818         /* Configure the CCR register with all communication parameters */
2819         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE  | OCTOSPI_CCR_IDTR  | OCTOSPI_CCR_ISIZE  |
2820                                 OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
2821                                 OCTOSPI_CCR_DMODE  | OCTOSPI_CCR_DDTR),
2822                                (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
2823                                 cmd->AddressMode     | cmd->AddressDtrMode     | cmd->AddressSize     |
2824                                 cmd->DataMode        | cmd->DataDtrMode));
2825       }
2826       else
2827       {
2828         /* ---- Command with instruction and address ---- */
2829 
2830         /* Configure the CCR register with all communication parameters */
2831         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE  | OCTOSPI_CCR_IDTR  | OCTOSPI_CCR_ISIZE  |
2832                                 OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
2833                                (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
2834                                 cmd->AddressMode     | cmd->AddressDtrMode     | cmd->AddressSize));
2835 
2836         /* The DHQC bit is linked with DDTR bit which should be activated */
2837         if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
2838             (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
2839         {
2840           MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
2841         }
2842       }
2843 
2844       /* Configure the IR register with the instruction value */
2845       *ir_reg = cmd->Instruction;
2846 
2847       /* Configure the AR register with the address value */
2848       hospi->Instance->AR = cmd->Address;
2849     }
2850     else
2851     {
2852       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
2853       {
2854         /* ---- Command with instruction and data ---- */
2855 
2856         /* Configure the CCR register with all communication parameters */
2857         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE |
2858                                 OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR),
2859                                (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
2860                                 cmd->DataMode        | cmd->DataDtrMode));
2861       }
2862       else
2863       {
2864         /* ---- Command with only instruction ---- */
2865 
2866         /* Configure the CCR register with all communication parameters */
2867         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE),
2868                                (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize));
2869 
2870         /* The DHQC bit is linked with DDTR bit which should be activated */
2871         if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
2872             (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
2873         {
2874           MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
2875         }
2876       }
2877 
2878       /* Configure the IR register with the instruction value */
2879       *ir_reg = cmd->Instruction;
2880 
2881     }
2882   }
2883   else
2884   {
2885     if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
2886     {
2887       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
2888       {
2889         /* ---- Command with address and data ---- */
2890 
2891         /* Configure the CCR register with all communication parameters */
2892         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
2893                                 OCTOSPI_CCR_DMODE  | OCTOSPI_CCR_DDTR),
2894                                (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize     |
2895                                 cmd->DataMode    | cmd->DataDtrMode));
2896       }
2897       else
2898       {
2899         /* ---- Command with only address ---- */
2900 
2901         /* Configure the CCR register with all communication parameters */
2902         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
2903                                (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize));
2904       }
2905 
2906       /* Configure the AR register with the instruction value */
2907       hospi->Instance->AR = cmd->Address;
2908     }
2909     else
2910     {
2911       /* ---- Invalid command configuration (no instruction, no address) ---- */
2912       status = HAL_ERROR;
2913       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
2914     }
2915   }
2916 
2917   /* Return function status */
2918   return status;
2919 }
2920 
2921 /**
2922   * @brief  Get the current IOM configuration for an OctoSPI instance.
2923   * @param  instance_nb : number of the instance
2924   * @param  cfg         : configuration of the IO Manager for the instance
2925   * @retval HAL status
2926   */
OSPIM_GetConfig(uint8_t instance_nb,OSPIM_CfgTypeDef * cfg)2927 static HAL_StatusTypeDef OSPIM_GetConfig(uint8_t instance_nb, OSPIM_CfgTypeDef *cfg)
2928 {
2929   HAL_StatusTypeDef status = HAL_OK;
2930   uint32_t reg, value = 0U;
2931   uint32_t index;
2932 
2933   if ((instance_nb == 0U) || (instance_nb > OSPI_NB_INSTANCE) || (cfg == NULL))
2934   {
2935     /* Invalid parameter -> error returned */
2936     status = HAL_ERROR;
2937   }
2938   else
2939   {
2940     /* Initialize the structure */
2941     cfg->ClkPort    = 0U;
2942     cfg->DQSPort    = 0U;
2943     cfg->NCSPort    = 0U;
2944     cfg->IOLowPort  = 0U;
2945     cfg->IOHighPort = 0U;
2946 
2947     if (instance_nb == 2U)
2948     {
2949       value = (OCTOSPIM_PCR_CLKSRC | OCTOSPIM_PCR_DQSSRC | OCTOSPIM_PCR_NCSSRC | OCTOSPIM_PCR_IOLSRC_1 | OCTOSPIM_PCR_IOHSRC_1);
2950     }
2951 
2952     /* Get the information about the instance */
2953     for (index = 0U; index < OSPI_IOM_NB_PORTS; index ++)
2954     {
2955       reg = OCTOSPIM->PCR[index];
2956 
2957       if ((reg & OCTOSPIM_PCR_CLKEN) != 0U)
2958       {
2959         /* The clock is enabled on this port */
2960         if ((reg & OCTOSPIM_PCR_CLKSRC) == (value & OCTOSPIM_PCR_CLKSRC))
2961         {
2962           /* The clock correspond to the instance passed as parameter */
2963           cfg->ClkPort = index+1U;
2964         }
2965       }
2966 
2967       if ((reg & OCTOSPIM_PCR_DQSEN) != 0U)
2968       {
2969         /* The DQS is enabled on this port */
2970         if ((reg & OCTOSPIM_PCR_DQSSRC) == (value & OCTOSPIM_PCR_DQSSRC))
2971         {
2972           /* The DQS correspond to the instance passed as parameter */
2973           cfg->DQSPort = index+1U;
2974         }
2975       }
2976 
2977       if ((reg & OCTOSPIM_PCR_NCSEN) != 0U)
2978       {
2979         /* The nCS is enabled on this port */
2980         if ((reg & OCTOSPIM_PCR_NCSSRC) == (value & OCTOSPIM_PCR_NCSSRC))
2981         {
2982           /* The nCS correspond to the instance passed as parameter */
2983           cfg->NCSPort = index+1U;
2984         }
2985       }
2986 
2987       if ((reg & OCTOSPIM_PCR_IOLEN) != 0U)
2988       {
2989         /* The IO Low is enabled on this port */
2990         if ((reg & OCTOSPIM_PCR_IOLSRC_1) == (value & OCTOSPIM_PCR_IOLSRC_1))
2991         {
2992           /* The IO Low correspond to the instance passed as parameter */
2993           if ((reg & OCTOSPIM_PCR_IOLSRC_0) == 0U)
2994           {
2995             cfg->IOLowPort = (OCTOSPIM_PCR_IOLEN | (index+1U));
2996           }
2997           else
2998           {
2999             cfg->IOLowPort = (OCTOSPIM_PCR_IOHEN | (index+1U));
3000           }
3001         }
3002       }
3003 
3004       if ((reg & OCTOSPIM_PCR_IOHEN) != 0U)
3005       {
3006         /* The IO High is enabled on this port */
3007         if ((reg & OCTOSPIM_PCR_IOHSRC_1) == (value & OCTOSPIM_PCR_IOHSRC_1))
3008         {
3009           /* The IO High correspond to the instance passed as parameter */
3010           if ((reg & OCTOSPIM_PCR_IOHSRC_0) == 0U)
3011           {
3012             cfg->IOHighPort = (OCTOSPIM_PCR_IOLEN | (index+1U));
3013           }
3014           else
3015           {
3016             cfg->IOHighPort = (OCTOSPIM_PCR_IOHEN | (index+1U));
3017           }
3018         }
3019       }
3020     }
3021   }
3022 
3023   /* Return function status */
3024   return status;
3025 }
3026 
3027 /**
3028   @endcond
3029   */
3030 
3031 /**
3032   * @}
3033   */
3034 
3035 #endif /* HAL_OSPI_MODULE_ENABLED */
3036 
3037 /**
3038   * @}
3039   */
3040 
3041 /**
3042   * @}
3043   */
3044 
3045 #endif /* OCTOSPI || OCTOSPI1 || OCTOSPI2 */
3046 
3047 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
3048