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