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       }
1152       while (hospi->XferCount > 0U);
1153 
1154       if (status == HAL_OK)
1155       {
1156         /* Wait till transfer complete flag is set to go back in idle state */
1157         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
1158 
1159         if (status == HAL_OK)
1160         {
1161           /* Clear transfer complete flag */
1162           __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
1163 
1164           /* Update state */
1165           hospi->State = HAL_OSPI_STATE_READY;
1166         }
1167       }
1168     }
1169     else
1170     {
1171       status = HAL_ERROR;
1172       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1173     }
1174   }
1175 
1176   /* Return function status */
1177   return status;
1178 }
1179 
1180 /**
1181   * @brief  Receive an amount of data in blocking mode.
1182   * @param  hospi   : OSPI handle
1183   * @param  pData   : pointer to data buffer
1184   * @param  Timeout : Timeout duration
1185   * @note   This function is used only in Indirect Read Mode
1186   * @retval HAL status
1187   */
HAL_OSPI_Receive(OSPI_HandleTypeDef * hospi,uint8_t * pData,uint32_t Timeout)1188 HAL_StatusTypeDef HAL_OSPI_Receive(OSPI_HandleTypeDef *hospi, uint8_t *pData, uint32_t Timeout)
1189 {
1190   HAL_StatusTypeDef status;
1191   uint32_t tickstart = HAL_GetTick();
1192   __IO uint32_t *data_reg = &hospi->Instance->DR;
1193   uint32_t addr_reg = hospi->Instance->AR;
1194   uint32_t ir_reg = hospi->Instance->IR;
1195 
1196   /* Check the data pointer allocation */
1197   if (pData == NULL)
1198   {
1199     status = HAL_ERROR;
1200     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1201   }
1202   else
1203   {
1204     /* Check the state */
1205     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1206     {
1207       /* Configure counters and size */
1208       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1209       hospi->XferSize  = hospi->XferCount;
1210       hospi->pBuffPtr  = pData;
1211 
1212       /* Configure CR register with functional mode as indirect read */
1213       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1214 
1215       /* Trig the transfer by re-writing address or instruction register */
1216       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1217       {
1218         WRITE_REG(hospi->Instance->AR, addr_reg);
1219       }
1220       else
1221       {
1222         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1223         {
1224           WRITE_REG(hospi->Instance->AR, addr_reg);
1225         }
1226         else
1227         {
1228           WRITE_REG(hospi->Instance->IR, ir_reg);
1229         }
1230       }
1231 
1232       do
1233       {
1234         /* Wait till fifo threshold or transfer complete flags are set to read received data */
1235         status = OSPI_WaitFlagStateUntilTimeout(hospi, (HAL_OSPI_FLAG_FT | HAL_OSPI_FLAG_TC), SET, tickstart, Timeout);
1236 
1237         if (status != HAL_OK)
1238         {
1239           break;
1240         }
1241 
1242         *hospi->pBuffPtr = *((__IO uint8_t *)data_reg);
1243         hospi->pBuffPtr++;
1244         hospi->XferCount--;
1245       }
1246       while (hospi->XferCount > 0U);
1247 
1248       if (status == HAL_OK)
1249       {
1250         /* Wait till transfer complete flag is set to go back in idle state */
1251         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, Timeout);
1252 
1253         if (status == HAL_OK)
1254         {
1255           /* Clear transfer complete flag */
1256           __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
1257 
1258           /* Update state */
1259           hospi->State = HAL_OSPI_STATE_READY;
1260         }
1261       }
1262     }
1263     else
1264     {
1265       status = HAL_ERROR;
1266       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1267     }
1268   }
1269 
1270   /* Return function status */
1271   return status;
1272 }
1273 
1274 /**
1275   * @brief  Send an amount of data in non-blocking mode with interrupt.
1276   * @param  hospi : OSPI handle
1277   * @param  pData : pointer to data buffer
1278   * @note   This function is used only in Indirect Write Mode
1279   * @retval HAL status
1280   */
HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef * hospi,uint8_t * pData)1281 HAL_StatusTypeDef HAL_OSPI_Transmit_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1282 {
1283   HAL_StatusTypeDef status = HAL_OK;
1284 
1285   /* Check the data pointer allocation */
1286   if (pData == NULL)
1287   {
1288     status = HAL_ERROR;
1289     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1290   }
1291   else
1292   {
1293     /* Check the state */
1294     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1295     {
1296       /* Configure counters and size */
1297       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1298       hospi->XferSize  = hospi->XferCount;
1299       hospi->pBuffPtr  = pData;
1300 
1301       /* Configure CR register with functional mode as indirect write */
1302       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
1303 
1304       /* Clear flags related to interrupt */
1305       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1306 
1307       /* Update the state */
1308       hospi->State = HAL_OSPI_STATE_BUSY_TX;
1309 
1310       /* Enable the transfer complete, fifo threshold and transfer error interrupts */
1311       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
1312     }
1313     else
1314     {
1315       status = HAL_ERROR;
1316       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1317     }
1318   }
1319 
1320   /* Return function status */
1321   return status;
1322 }
1323 
1324 /**
1325   * @brief  Receive an amount of data in non-blocking mode with interrupt.
1326   * @param  hospi : OSPI handle
1327   * @param  pData : pointer to data buffer
1328   * @note   This function is used only in Indirect Read Mode
1329   * @retval HAL status
1330   */
HAL_OSPI_Receive_IT(OSPI_HandleTypeDef * hospi,uint8_t * pData)1331 HAL_StatusTypeDef HAL_OSPI_Receive_IT(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1332 {
1333   HAL_StatusTypeDef status = HAL_OK;
1334   uint32_t addr_reg = hospi->Instance->AR;
1335   uint32_t ir_reg = hospi->Instance->IR;
1336 
1337   /* Check the data pointer allocation */
1338   if (pData == NULL)
1339   {
1340     status = HAL_ERROR;
1341     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1342   }
1343   else
1344   {
1345     /* Check the state */
1346     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1347     {
1348       /* Configure counters and size */
1349       hospi->XferCount = READ_REG(hospi->Instance->DLR) + 1U;
1350       hospi->XferSize  = hospi->XferCount;
1351       hospi->pBuffPtr  = pData;
1352 
1353       /* Configure CR register with functional mode as indirect read */
1354       MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1355 
1356       /* Clear flags related to interrupt */
1357       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1358 
1359       /* Update the state */
1360       hospi->State = HAL_OSPI_STATE_BUSY_RX;
1361 
1362       /* Enable the transfer complete, fifo threshold and transfer error interrupts */
1363       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
1364 
1365       /* Trig the transfer by re-writing address or instruction register */
1366       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1367       {
1368         WRITE_REG(hospi->Instance->AR, addr_reg);
1369       }
1370       else
1371       {
1372         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1373         {
1374           WRITE_REG(hospi->Instance->AR, addr_reg);
1375         }
1376         else
1377         {
1378           WRITE_REG(hospi->Instance->IR, ir_reg);
1379         }
1380       }
1381     }
1382     else
1383     {
1384       status = HAL_ERROR;
1385       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1386     }
1387   }
1388 
1389   /* Return function status */
1390   return status;
1391 }
1392 
1393 /**
1394   * @brief  Send an amount of data in non-blocking mode with DMA.
1395   * @param  hospi : OSPI handle
1396   * @param  pData : pointer to data buffer
1397   * @note   This function is used only in Indirect Write Mode
1398   * @note   If DMA peripheral access is configured as halfword, the number
1399   *         of data and the fifo threshold should be aligned on halfword
1400   * @note   If DMA peripheral access is configured as word, the number
1401   *         of data and the fifo threshold should be aligned on word
1402   * @retval HAL status
1403   */
HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef * hospi,uint8_t * pData)1404 HAL_StatusTypeDef HAL_OSPI_Transmit_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1405 {
1406   HAL_StatusTypeDef status = HAL_OK;
1407   uint32_t data_size = hospi->Instance->DLR + 1U;
1408   DMA_QListTypeDef *p_queue = {NULL};
1409   uint32_t data_width = DMA_DEST_DATAWIDTH_BYTE;
1410 
1411   /* Check the data pointer allocation */
1412   if (pData == NULL)
1413   {
1414     status = HAL_ERROR;
1415     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1416   }
1417   else
1418   {
1419     /* Check the state */
1420     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1421     {
1422       if ((hospi->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1423       {
1424         p_queue = hospi->hdma->LinkedListQueue;
1425         if ((p_queue != NULL) && (p_queue->Head != NULL))
1426         {
1427           data_width = p_queue->Head->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_DDW_LOG2;
1428         }
1429         else
1430         {
1431           /* Set Error Code */
1432           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1433 
1434           /* Return function status */
1435           status = HAL_ERROR;
1436         }
1437       }
1438       else
1439       {
1440         data_width = hospi->hdma->Init.DestDataWidth;
1441       }
1442       /* Configure counters and size */
1443       if (data_width == DMA_DEST_DATAWIDTH_BYTE)
1444       {
1445         hospi->XferCount = data_size;
1446       }
1447       else if (data_width == DMA_DEST_DATAWIDTH_HALFWORD)
1448       {
1449         if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U))
1450         {
1451           /* The number of data or the fifo threshold is not aligned on halfword
1452           => no transfer possible with DMA peripheral access configured as halfword */
1453           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1454           status = HAL_ERROR;
1455         }
1456         else
1457         {
1458           hospi->XferCount = data_size;
1459         }
1460       }
1461       else if (data_width == DMA_DEST_DATAWIDTH_WORD)
1462       {
1463         if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U))
1464         {
1465           /* The number of data or the fifo threshold is not aligned on word
1466           => no transfer possible with DMA peripheral access configured as word */
1467           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1468           status = HAL_ERROR;
1469         }
1470         else
1471         {
1472           hospi->XferCount = data_size;
1473         }
1474       }
1475       else
1476       {
1477         /* Nothing to do */
1478       }
1479 
1480       if (status == HAL_OK)
1481       {
1482         hospi->XferSize = hospi->XferCount;
1483         hospi->pBuffPtr = pData;
1484 
1485         /* Configure CR register with functional mode as indirect write */
1486         MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_WRITE);
1487 
1488         /* Clear flags related to interrupt */
1489         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1490 
1491         /* Update the state */
1492         hospi->State = HAL_OSPI_STATE_BUSY_TX;
1493 
1494         /* Set the DMA transfer complete callback */
1495         hospi->hdma->XferCpltCallback = OSPI_DMACplt;
1496 
1497         /* Set the DMA Half transfer complete callback */
1498         hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt;
1499 
1500         /* Set the DMA error callback */
1501         hospi->hdma->XferErrorCallback = OSPI_DMAError;
1502 
1503         /* Clear the DMA abort callback */
1504         hospi->hdma->XferAbortCallback = NULL;
1505 
1506         /* Enable the transmit DMA Channel */
1507         if ((hospi->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1508         {
1509           if (hospi->hdma->LinkedListQueue != NULL)
1510           {
1511             /* Enable the DMA channel */
1512             MODIFY_REG(p_queue->Head->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET], \
1513                        (DMA_CTR1_SINC | DMA_CTR1_DINC), (DMA_SINC_INCREMENTED | DMA_DINC_FIXED));
1514             MODIFY_REG(p_queue->Head->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET], \
1515                        DMA_CTR2_DREQ, DMA_MEMORY_TO_PERIPH);
1516             /* Set DMA data size*/
1517             p_queue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hospi->XferSize;
1518             /* Set DMA source address */
1519             p_queue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)pData;
1520             /* Set DMA destination address */
1521             p_queue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)&hospi->Instance->DR;
1522             status = HAL_DMAEx_List_Start_IT(hospi->hdma);
1523           }
1524           else
1525           {
1526             /* Set Error Code */
1527             hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1528 
1529             /* Change OSPI state */
1530             hospi->State = HAL_OSPI_STATE_READY;
1531 
1532             /* Return function status */
1533             status = HAL_ERROR;
1534           }
1535         }
1536         else
1537         {
1538           /* Configure the direction of the DMA */
1539           MODIFY_REG(hospi->hdma->Instance->CTR1, (DMA_CTR1_SINC | DMA_CTR1_DINC), \
1540                      (DMA_SINC_INCREMENTED | DMA_DINC_FIXED));
1541           MODIFY_REG(hospi->hdma->Instance->CTR2, DMA_CTR2_DREQ, DMA_MEMORY_TO_PERIPH);
1542 
1543           status = HAL_DMA_Start_IT(hospi->hdma, (uint32_t)pData, (uint32_t)&hospi->Instance->DR, hospi->XferSize);
1544         }
1545 
1546         if (status == HAL_OK)
1547         {
1548           /* Enable the transfer error interrupt */
1549           __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
1550 
1551           /* Enable the DMA transfer by setting the DMAEN bit  */
1552           SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
1553         }
1554         else
1555         {
1556           status = HAL_ERROR;
1557           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1558           hospi->State = HAL_OSPI_STATE_READY;
1559         }
1560       }
1561     }
1562     else
1563     {
1564       status = HAL_ERROR;
1565       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1566     }
1567   }
1568 
1569   /* Return function status */
1570   return status;
1571 }
1572 
1573 /**
1574   * @brief  Receive an amount of data in non-blocking mode with DMA.
1575   * @param  hospi : OSPI handle
1576   * @param  pData : pointer to data buffer.
1577   * @note   This function is used only in Indirect Read Mode
1578   * @note   If DMA peripheral access is configured as halfword, the number
1579   *         of data and the fifo threshold should be aligned on halfword
1580   * @note   If DMA peripheral access is configured as word, the number
1581   *         of data and the fifo threshold should be aligned on word
1582   * @retval HAL status
1583   */
HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef * hospi,uint8_t * pData)1584 HAL_StatusTypeDef HAL_OSPI_Receive_DMA(OSPI_HandleTypeDef *hospi, uint8_t *pData)
1585 {
1586   HAL_StatusTypeDef status = HAL_OK;
1587   uint32_t data_size = hospi->Instance->DLR + 1U;
1588   uint32_t addr_reg = hospi->Instance->AR;
1589   uint32_t ir_reg = hospi->Instance->IR;
1590   DMA_QListTypeDef *p_queue = {NULL};
1591   uint32_t data_width = DMA_DEST_DATAWIDTH_BYTE;
1592   /* Check the data pointer allocation */
1593   if (pData == NULL)
1594   {
1595     status = HAL_ERROR;
1596     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1597   }
1598   else
1599   {
1600     /* Check the state */
1601     if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1602     {
1603       if ((hospi->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1604       {
1605         p_queue = hospi->hdma->LinkedListQueue;
1606         if ((p_queue != NULL) && (p_queue->Head != NULL))
1607         {
1608           data_width = p_queue->Head->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET] & DMA_CTR1_DDW_LOG2;
1609         }
1610         else
1611         {
1612           /* Set Error Code */
1613           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1614 
1615           /* Return function status */
1616           status = HAL_ERROR;
1617         }
1618       }
1619       else
1620       {
1621         data_width = hospi->hdma->Init.DestDataWidth;
1622       }
1623 
1624       /* Configure counters and size */
1625       if (data_width == DMA_DEST_DATAWIDTH_BYTE)
1626       {
1627         hospi->XferCount = data_size;
1628       }
1629       else if (data_width == DMA_DEST_DATAWIDTH_HALFWORD)
1630       {
1631         if (((data_size % 2U) != 0U) || ((hospi->Init.FifoThreshold % 2U) != 0U))
1632         {
1633           /* The number of data or the fifo threshold is not aligned on halfword
1634           => no transfer possible with DMA peripheral access configured as halfword */
1635           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1636           status = HAL_ERROR;
1637         }
1638         else
1639         {
1640           hospi->XferCount = data_size;
1641         }
1642       }
1643       else if (data_width == DMA_DEST_DATAWIDTH_WORD)
1644       {
1645         if (((data_size % 4U) != 0U) || ((hospi->Init.FifoThreshold % 4U) != 0U))
1646         {
1647           /* The number of data or the fifo threshold is not aligned on word
1648           => no transfer possible with DMA peripheral access configured as word */
1649           hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
1650           status = HAL_ERROR;
1651         }
1652         else
1653         {
1654           hospi->XferCount = data_size;
1655         }
1656       }
1657       else
1658       {
1659         /* Nothing to do */
1660       }
1661 
1662       if (status == HAL_OK)
1663       {
1664         hospi->XferSize  = hospi->XferCount;
1665         hospi->pBuffPtr  = pData;
1666 
1667         /* Configure CR register with functional mode as indirect read */
1668         MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);
1669 
1670         /* Clear flags related to interrupt */
1671         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_TC);
1672 
1673         /* Update the state */
1674         hospi->State = HAL_OSPI_STATE_BUSY_RX;
1675 
1676         /* Set the DMA transfer complete callback */
1677         hospi->hdma->XferCpltCallback = OSPI_DMACplt;
1678 
1679         /* Set the DMA Half transfer complete callback */
1680         hospi->hdma->XferHalfCpltCallback = OSPI_DMAHalfCplt;
1681 
1682         /* Set the DMA error callback */
1683         hospi->hdma->XferErrorCallback = OSPI_DMAError;
1684 
1685         /* Clear the DMA abort callback */
1686         hospi->hdma->XferAbortCallback = NULL;
1687 
1688         /* Enable the transmit DMA Channel */
1689         if ((hospi->hdma->Mode & DMA_LINKEDLIST) == DMA_LINKEDLIST)
1690         {
1691           if (hospi->hdma->LinkedListQueue != NULL)
1692           {
1693             /* Enable the DMA channel */
1694             MODIFY_REG(p_queue->Head->LinkRegisters[NODE_CTR1_DEFAULT_OFFSET], \
1695                        (DMA_CTR1_SINC | DMA_CTR1_DINC), (DMA_SINC_FIXED | DMA_DINC_INCREMENTED));
1696             MODIFY_REG(p_queue->Head->LinkRegisters[NODE_CTR2_DEFAULT_OFFSET], \
1697                        DMA_CTR2_DREQ, DMA_PERIPH_TO_MEMORY);
1698             /* Set DMA data size */
1699             p_queue->Head->LinkRegisters[NODE_CBR1_DEFAULT_OFFSET] = hospi->XferSize;
1700             /* Set DMA source address */
1701             p_queue->Head->LinkRegisters[NODE_CSAR_DEFAULT_OFFSET] = (uint32_t)&hospi->Instance->DR;
1702             /* Set DMA destination address */
1703             p_queue->Head->LinkRegisters[NODE_CDAR_DEFAULT_OFFSET] = (uint32_t)pData;
1704 
1705             status = HAL_DMAEx_List_Start_IT(hospi->hdma);
1706           }
1707           else
1708           {
1709             /* Set Error Code */
1710             hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1711 
1712             /* Change OSPI state */
1713             hospi->State = HAL_OSPI_STATE_READY;
1714 
1715             /* Return function status */
1716             status = HAL_ERROR;
1717           }
1718         }
1719 
1720 
1721         else
1722         {
1723           /* Configure the direction of the DMA */
1724           MODIFY_REG(hospi->hdma->Instance->CTR1, (DMA_CTR1_SINC | DMA_CTR1_DINC), \
1725                      (DMA_SINC_FIXED | DMA_DINC_INCREMENTED));
1726           MODIFY_REG(hospi->hdma->Instance->CTR2, DMA_CTR2_DREQ, DMA_PERIPH_TO_MEMORY);
1727 
1728           status = HAL_DMA_Start_IT(hospi->hdma, (uint32_t)&hospi->Instance->DR, (uint32_t)pData, hospi->XferSize);
1729         }
1730         if (status == HAL_OK)
1731         {
1732           /* Enable the transfer error interrupt */
1733           __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TE);
1734 
1735           /* Trig the transfer by re-writing address or instruction register */
1736           if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1737           {
1738             WRITE_REG(hospi->Instance->AR, addr_reg);
1739           }
1740           else
1741           {
1742             if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1743             {
1744               WRITE_REG(hospi->Instance->AR, addr_reg);
1745             }
1746             else
1747             {
1748               WRITE_REG(hospi->Instance->IR, ir_reg);
1749             }
1750           }
1751 
1752           /* Enable the DMA transfer by setting the DMAEN bit  */
1753           SET_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
1754         }
1755         else
1756         {
1757           status = HAL_ERROR;
1758           hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
1759           hospi->State = HAL_OSPI_STATE_READY;
1760         }
1761       }
1762     }
1763     else
1764     {
1765       status = HAL_ERROR;
1766       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1767     }
1768   }
1769 
1770   /* Return function status */
1771   return status;
1772 }
1773 
1774 /**
1775   * @brief  Configure the OSPI Automatic Polling Mode in blocking mode.
1776   * @param  hospi   : OSPI handle
1777   * @param  cfg     : structure that contains the polling configuration information.
1778   * @param  Timeout : Timeout duration
1779   * @note   This function is used only in Automatic Polling Mode
1780   * @retval HAL status
1781   */
HAL_OSPI_AutoPolling(OSPI_HandleTypeDef * hospi,OSPI_AutoPollingTypeDef * cfg,uint32_t Timeout)1782 HAL_StatusTypeDef HAL_OSPI_AutoPolling(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
1783 {
1784   HAL_StatusTypeDef status;
1785   uint32_t tickstart = HAL_GetTick();
1786   uint32_t addr_reg = hospi->Instance->AR;
1787   uint32_t ir_reg = hospi->Instance->IR;
1788 #ifdef USE_FULL_ASSERT
1789   uint32_t dlr_reg = hospi->Instance->DLR;
1790 #endif /* USE_FULL_ASSERT */
1791 
1792   /* Check the parameters of the autopolling configuration structure */
1793   assert_param(IS_OSPI_MATCH_MODE(cfg->MatchMode));
1794   assert_param(IS_OSPI_AUTOMATIC_STOP(cfg->AutomaticStop));
1795   assert_param(IS_OSPI_INTERVAL(cfg->Interval));
1796   assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg + 1U));
1797 
1798   /* Check the state */
1799   if ((hospi->State == HAL_OSPI_STATE_CMD_CFG) && (cfg->AutomaticStop == HAL_OSPI_AUTOMATIC_STOP_ENABLE))
1800   {
1801     /* Wait till busy flag is reset */
1802     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
1803 
1804     if (status == HAL_OK)
1805     {
1806       /* Configure registers */
1807       WRITE_REG(hospi->Instance->PSMAR, cfg->Match);
1808       WRITE_REG(hospi->Instance->PSMKR, cfg->Mask);
1809       WRITE_REG(hospi->Instance->PIR,   cfg->Interval);
1810       MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
1811                  (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
1812 
1813       /* Trig the transfer by re-writing address or instruction register */
1814       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1815       {
1816         WRITE_REG(hospi->Instance->AR, addr_reg);
1817       }
1818       else
1819       {
1820         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1821         {
1822           WRITE_REG(hospi->Instance->AR, addr_reg);
1823         }
1824         else
1825         {
1826           WRITE_REG(hospi->Instance->IR, ir_reg);
1827         }
1828       }
1829 
1830       /* Wait till status match flag is set to go back in idle state */
1831       status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout);
1832 
1833       if (status == HAL_OK)
1834       {
1835         /* Clear status match flag */
1836         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_SM);
1837 
1838         /* Update state */
1839         hospi->State = HAL_OSPI_STATE_READY;
1840       }
1841     }
1842   }
1843   else
1844   {
1845     status = HAL_ERROR;
1846     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1847   }
1848 
1849   /* Return function status */
1850   return status;
1851 }
1852 
1853 /**
1854   * @brief  Configure the OSPI Automatic Polling Mode in non-blocking mode.
1855   * @param  hospi : OSPI handle
1856   * @param  cfg   : structure that contains the polling configuration information.
1857   * @note   This function is used only in Automatic Polling Mode
1858   * @retval HAL status
1859   */
HAL_OSPI_AutoPolling_IT(OSPI_HandleTypeDef * hospi,OSPI_AutoPollingTypeDef * cfg)1860 HAL_StatusTypeDef HAL_OSPI_AutoPolling_IT(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg)
1861 {
1862   HAL_StatusTypeDef status;
1863   uint32_t tickstart = HAL_GetTick();
1864   uint32_t addr_reg = hospi->Instance->AR;
1865   uint32_t ir_reg = hospi->Instance->IR;
1866 #ifdef USE_FULL_ASSERT
1867   uint32_t dlr_reg = hospi->Instance->DLR;
1868 #endif /* USE_FULL_ASSERT */
1869 
1870   /* Check the parameters of the autopolling configuration structure */
1871   assert_param(IS_OSPI_MATCH_MODE(cfg->MatchMode));
1872   assert_param(IS_OSPI_AUTOMATIC_STOP(cfg->AutomaticStop));
1873   assert_param(IS_OSPI_INTERVAL(cfg->Interval));
1874   assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg + 1U));
1875 
1876   /* Check the state */
1877   if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1878   {
1879     /* Wait till busy flag is reset */
1880     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
1881 
1882     if (status == HAL_OK)
1883     {
1884       /* Configure registers */
1885       WRITE_REG(hospi->Instance->PSMAR, cfg->Match);
1886       WRITE_REG(hospi->Instance->PSMKR, cfg->Mask);
1887       WRITE_REG(hospi->Instance->PIR,   cfg->Interval);
1888       MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
1889                  (cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
1890 
1891       /* Clear flags related to interrupt */
1892       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TE | HAL_OSPI_FLAG_SM);
1893 
1894       /* Update state */
1895       hospi->State = HAL_OSPI_STATE_BUSY_AUTO_POLLING;
1896 
1897       /* Enable the status match and transfer error interrupts */
1898       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_SM | HAL_OSPI_IT_TE);
1899 
1900       /* Trig the transfer by re-writing address or instruction register */
1901       if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
1902       {
1903         WRITE_REG(hospi->Instance->AR, addr_reg);
1904       }
1905       else
1906       {
1907         if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
1908         {
1909           WRITE_REG(hospi->Instance->AR, addr_reg);
1910         }
1911         else
1912         {
1913           WRITE_REG(hospi->Instance->IR, ir_reg);
1914         }
1915       }
1916     }
1917   }
1918   else
1919   {
1920     status = HAL_ERROR;
1921     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1922   }
1923 
1924   /* Return function status */
1925   return status;
1926 }
1927 
1928 /**
1929   * @brief  Configure the Memory Mapped mode.
1930   * @param  hospi : OSPI handle
1931   * @param  cfg   : structure that contains the memory mapped configuration information.
1932   * @note   This function is used only in Memory mapped Mode
1933   * @retval HAL status
1934   */
HAL_OSPI_MemoryMapped(OSPI_HandleTypeDef * hospi,OSPI_MemoryMappedTypeDef * cfg)1935 HAL_StatusTypeDef HAL_OSPI_MemoryMapped(OSPI_HandleTypeDef *hospi, OSPI_MemoryMappedTypeDef *cfg)
1936 {
1937   HAL_StatusTypeDef status;
1938   uint32_t tickstart = HAL_GetTick();
1939 
1940   /* Check the parameters of the memory-mapped configuration structure */
1941   assert_param(IS_OSPI_TIMEOUT_ACTIVATION(cfg->TimeOutActivation));
1942 
1943   /* Check the state */
1944   if (hospi->State == HAL_OSPI_STATE_CMD_CFG)
1945   {
1946     /* Wait till busy flag is reset */
1947     status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
1948 
1949     if (status == HAL_OK)
1950     {
1951       /* Update state */
1952       hospi->State = HAL_OSPI_STATE_BUSY_MEM_MAPPED;
1953 
1954       if (cfg->TimeOutActivation == HAL_OSPI_TIMEOUT_COUNTER_ENABLE)
1955       {
1956         assert_param(IS_OSPI_TIMEOUT_PERIOD(cfg->TimeOutPeriod));
1957 
1958         /* Configure register */
1959         WRITE_REG(hospi->Instance->LPTR, cfg->TimeOutPeriod);
1960 
1961         /* Clear flags related to interrupt */
1962         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TO);
1963 
1964         /* Enable the timeout interrupt */
1965         __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TO);
1966       }
1967 
1968       /* Configure CR register with functional mode as memory-mapped */
1969       MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_TCEN | OCTOSPI_CR_FMODE),
1970                  (cfg->TimeOutActivation | OSPI_FUNCTIONAL_MODE_MEMORY_MAPPED));
1971     }
1972   }
1973   else
1974   {
1975     status = HAL_ERROR;
1976     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
1977   }
1978 
1979   /* Return function status */
1980   return status;
1981 }
1982 
1983 /**
1984   * @brief  Transfer Error callback.
1985   * @param  hospi : OSPI handle
1986   * @retval None
1987   */
HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef * hospi)1988 __weak void HAL_OSPI_ErrorCallback(OSPI_HandleTypeDef *hospi)
1989 {
1990   /* Prevent unused argument(s) compilation warning */
1991   UNUSED(hospi);
1992 
1993   /* NOTE : This function should not be modified, when the callback is needed,
1994             the HAL_OSPI_ErrorCallback could be implemented in the user file
1995    */
1996 }
1997 
1998 /**
1999   * @brief  Abort completed callback.
2000   * @param  hospi : OSPI handle
2001   * @retval None
2002   */
HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef * hospi)2003 __weak void HAL_OSPI_AbortCpltCallback(OSPI_HandleTypeDef *hospi)
2004 {
2005   /* Prevent unused argument(s) compilation warning */
2006   UNUSED(hospi);
2007 
2008   /* NOTE: This function should not be modified, when the callback is needed,
2009            the HAL_OSPI_AbortCpltCallback could be implemented in the user file
2010    */
2011 }
2012 
2013 /**
2014   * @brief  FIFO Threshold callback.
2015   * @param  hospi : OSPI handle
2016   * @retval None
2017   */
HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef * hospi)2018 __weak void HAL_OSPI_FifoThresholdCallback(OSPI_HandleTypeDef *hospi)
2019 {
2020   /* Prevent unused argument(s) compilation warning */
2021   UNUSED(hospi);
2022 
2023   /* NOTE : This function should not be modified, when the callback is needed,
2024             the HAL_OSPI_FIFOThresholdCallback could be implemented in the user file
2025    */
2026 }
2027 
2028 /**
2029   * @brief  Command completed callback.
2030   * @param  hospi : OSPI handle
2031   * @retval None
2032   */
HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef * hospi)2033 __weak void HAL_OSPI_CmdCpltCallback(OSPI_HandleTypeDef *hospi)
2034 {
2035   /* Prevent unused argument(s) compilation warning */
2036   UNUSED(hospi);
2037 
2038   /* NOTE: This function should not be modified, when the callback is needed,
2039            the HAL_OSPI_CmdCpltCallback could be implemented in the user file
2040    */
2041 }
2042 
2043 /**
2044   * @brief  Rx Transfer completed callback.
2045   * @param  hospi : OSPI handle
2046   * @retval None
2047   */
HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef * hospi)2048 __weak void HAL_OSPI_RxCpltCallback(OSPI_HandleTypeDef *hospi)
2049 {
2050   /* Prevent unused argument(s) compilation warning */
2051   UNUSED(hospi);
2052 
2053   /* NOTE: This function should not be modified, when the callback is needed,
2054            the HAL_OSPI_RxCpltCallback could be implemented in the user file
2055    */
2056 }
2057 
2058 /**
2059   * @brief  Tx Transfer completed callback.
2060   * @param  hospi : OSPI handle
2061   * @retval None
2062   */
HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef * hospi)2063 __weak void HAL_OSPI_TxCpltCallback(OSPI_HandleTypeDef *hospi)
2064 {
2065   /* Prevent unused argument(s) compilation warning */
2066   UNUSED(hospi);
2067 
2068   /* NOTE: This function should not be modified, when the callback is needed,
2069            the HAL_OSPI_TxCpltCallback could be implemented in the user file
2070    */
2071 }
2072 
2073 /**
2074   * @brief  Rx Half Transfer completed callback.
2075   * @param  hospi : OSPI handle
2076   * @retval None
2077   */
HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef * hospi)2078 __weak void HAL_OSPI_RxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
2079 {
2080   /* Prevent unused argument(s) compilation warning */
2081   UNUSED(hospi);
2082 
2083   /* NOTE: This function should not be modified, when the callback is needed,
2084            the HAL_OSPI_RxHalfCpltCallback could be implemented in the user file
2085    */
2086 }
2087 
2088 /**
2089   * @brief  Tx Half Transfer completed callback.
2090   * @param  hospi : OSPI handle
2091   * @retval None
2092   */
HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef * hospi)2093 __weak void HAL_OSPI_TxHalfCpltCallback(OSPI_HandleTypeDef *hospi)
2094 {
2095   /* Prevent unused argument(s) compilation warning */
2096   UNUSED(hospi);
2097 
2098   /* NOTE: This function should not be modified, when the callback is needed,
2099            the HAL_OSPI_TxHalfCpltCallback could be implemented in the user file
2100    */
2101 }
2102 
2103 /**
2104   * @brief  Status Match callback.
2105   * @param  hospi : OSPI handle
2106   * @retval None
2107   */
HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef * hospi)2108 __weak void HAL_OSPI_StatusMatchCallback(OSPI_HandleTypeDef *hospi)
2109 {
2110   /* Prevent unused argument(s) compilation warning */
2111   UNUSED(hospi);
2112 
2113   /* NOTE : This function should not be modified, when the callback is needed,
2114             the HAL_OSPI_StatusMatchCallback could be implemented in the user file
2115    */
2116 }
2117 
2118 /**
2119   * @brief  Timeout callback.
2120   * @param  hospi : OSPI handle
2121   * @retval None
2122   */
HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef * hospi)2123 __weak void HAL_OSPI_TimeOutCallback(OSPI_HandleTypeDef *hospi)
2124 {
2125   /* Prevent unused argument(s) compilation warning */
2126   UNUSED(hospi);
2127 
2128   /* NOTE : This function should not be modified, when the callback is needed,
2129             the HAL_OSPI_TimeOutCallback could be implemented in the user file
2130    */
2131 }
2132 
2133 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2134 /**
2135   * @brief  Register a User OSPI Callback
2136   *         To be used to override the weak predefined callback
2137   * @param hospi : OSPI handle
2138   * @param CallbackID : ID of the callback to be registered
2139   *        This parameter can be one of the following values:
2140   *          @arg @ref HAL_OSPI_ERROR_CB_ID          OSPI Error Callback ID
2141   *          @arg @ref HAL_OSPI_ABORT_CB_ID          OSPI Abort Callback ID
2142   *          @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
2143   *          @arg @ref HAL_OSPI_CMD_CPLT_CB_ID       OSPI Command Complete Callback ID
2144   *          @arg @ref HAL_OSPI_RX_CPLT_CB_ID        OSPI Rx Complete Callback ID
2145   *          @arg @ref HAL_OSPI_TX_CPLT_CB_ID        OSPI Tx Complete Callback ID
2146   *          @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID   OSPI Rx Half Complete Callback ID
2147   *          @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID   OSPI Tx Half Complete Callback ID
2148   *          @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID   OSPI Status Match Callback ID
2149   *          @arg @ref HAL_OSPI_TIMEOUT_CB_ID        OSPI Timeout Callback ID
2150   *          @arg @ref HAL_OSPI_MSP_INIT_CB_ID       OSPI MspInit callback ID
2151   *          @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID     OSPI MspDeInit callback ID
2152   * @param pCallback : pointer to the Callback function
2153   * @retval status
2154   */
HAL_OSPI_RegisterCallback(OSPI_HandleTypeDef * hospi,HAL_OSPI_CallbackIDTypeDef CallbackID,pOSPI_CallbackTypeDef pCallback)2155 HAL_StatusTypeDef HAL_OSPI_RegisterCallback(OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID,
2156                                             pOSPI_CallbackTypeDef pCallback)
2157 {
2158   HAL_StatusTypeDef status = HAL_OK;
2159 
2160   if (pCallback == NULL)
2161   {
2162     /* Update the error code */
2163     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2164     return HAL_ERROR;
2165   }
2166 
2167   if (hospi->State == HAL_OSPI_STATE_READY)
2168   {
2169     switch (CallbackID)
2170     {
2171       case  HAL_OSPI_ERROR_CB_ID :
2172         hospi->ErrorCallback = pCallback;
2173         break;
2174       case HAL_OSPI_ABORT_CB_ID :
2175         hospi->AbortCpltCallback = pCallback;
2176         break;
2177       case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
2178         hospi->FifoThresholdCallback = pCallback;
2179         break;
2180       case HAL_OSPI_CMD_CPLT_CB_ID :
2181         hospi->CmdCpltCallback = pCallback;
2182         break;
2183       case HAL_OSPI_RX_CPLT_CB_ID :
2184         hospi->RxCpltCallback = pCallback;
2185         break;
2186       case HAL_OSPI_TX_CPLT_CB_ID :
2187         hospi->TxCpltCallback = pCallback;
2188         break;
2189       case HAL_OSPI_RX_HALF_CPLT_CB_ID :
2190         hospi->RxHalfCpltCallback = pCallback;
2191         break;
2192       case HAL_OSPI_TX_HALF_CPLT_CB_ID :
2193         hospi->TxHalfCpltCallback = pCallback;
2194         break;
2195       case HAL_OSPI_STATUS_MATCH_CB_ID :
2196         hospi->StatusMatchCallback = pCallback;
2197         break;
2198       case HAL_OSPI_TIMEOUT_CB_ID :
2199         hospi->TimeOutCallback = pCallback;
2200         break;
2201       case HAL_OSPI_MSP_INIT_CB_ID :
2202         hospi->MspInitCallback = pCallback;
2203         break;
2204       case HAL_OSPI_MSP_DEINIT_CB_ID :
2205         hospi->MspDeInitCallback = pCallback;
2206         break;
2207       default :
2208         /* Update the error code */
2209         hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2210         /* update return status */
2211         status =  HAL_ERROR;
2212         break;
2213     }
2214   }
2215   else if (hospi->State == HAL_OSPI_STATE_RESET)
2216   {
2217     switch (CallbackID)
2218     {
2219       case HAL_OSPI_MSP_INIT_CB_ID :
2220         hospi->MspInitCallback = pCallback;
2221         break;
2222       case HAL_OSPI_MSP_DEINIT_CB_ID :
2223         hospi->MspDeInitCallback = pCallback;
2224         break;
2225       default :
2226         /* Update the error code */
2227         hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2228         /* update return status */
2229         status =  HAL_ERROR;
2230         break;
2231     }
2232   }
2233   else
2234   {
2235     /* Update the error code */
2236     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2237     /* update return status */
2238     status =  HAL_ERROR;
2239   }
2240 
2241   return status;
2242 }
2243 
2244 /**
2245   * @brief  Unregister a User OSPI Callback
2246   *         OSPI Callback is redirected to the weak predefined callback
2247   * @param hospi : OSPI handle
2248   * @param CallbackID : ID of the callback to be unregistered
2249   *        This parameter can be one of the following values:
2250   *          @arg @ref HAL_OSPI_ERROR_CB_ID          OSPI Error Callback ID
2251   *          @arg @ref HAL_OSPI_ABORT_CB_ID          OSPI Abort Callback ID
2252   *          @arg @ref HAL_OSPI_FIFO_THRESHOLD_CB_ID OSPI FIFO Threshold Callback ID
2253   *          @arg @ref HAL_OSPI_CMD_CPLT_CB_ID       OSPI Command Complete Callback ID
2254   *          @arg @ref HAL_OSPI_RX_CPLT_CB_ID        OSPI Rx Complete Callback ID
2255   *          @arg @ref HAL_OSPI_TX_CPLT_CB_ID        OSPI Tx Complete Callback ID
2256   *          @arg @ref HAL_OSPI_RX_HALF_CPLT_CB_ID   OSPI Rx Half Complete Callback ID
2257   *          @arg @ref HAL_OSPI_TX_HALF_CPLT_CB_ID   OSPI Tx Half Complete Callback ID
2258   *          @arg @ref HAL_OSPI_STATUS_MATCH_CB_ID   OSPI Status Match Callback ID
2259   *          @arg @ref HAL_OSPI_TIMEOUT_CB_ID        OSPI Timeout Callback ID
2260   *          @arg @ref HAL_OSPI_MSP_INIT_CB_ID       OSPI MspInit callback ID
2261   *          @arg @ref HAL_OSPI_MSP_DEINIT_CB_ID     OSPI MspDeInit callback ID
2262   * @retval status
2263   */
HAL_OSPI_UnRegisterCallback(OSPI_HandleTypeDef * hospi,HAL_OSPI_CallbackIDTypeDef CallbackID)2264 HAL_StatusTypeDef HAL_OSPI_UnRegisterCallback(OSPI_HandleTypeDef *hospi, HAL_OSPI_CallbackIDTypeDef CallbackID)
2265 {
2266   HAL_StatusTypeDef status = HAL_OK;
2267 
2268   if (hospi->State == HAL_OSPI_STATE_READY)
2269   {
2270     switch (CallbackID)
2271     {
2272       case  HAL_OSPI_ERROR_CB_ID :
2273         hospi->ErrorCallback = HAL_OSPI_ErrorCallback;
2274         break;
2275       case HAL_OSPI_ABORT_CB_ID :
2276         hospi->AbortCpltCallback = HAL_OSPI_AbortCpltCallback;
2277         break;
2278       case HAL_OSPI_FIFO_THRESHOLD_CB_ID :
2279         hospi->FifoThresholdCallback = HAL_OSPI_FifoThresholdCallback;
2280         break;
2281       case HAL_OSPI_CMD_CPLT_CB_ID :
2282         hospi->CmdCpltCallback = HAL_OSPI_CmdCpltCallback;
2283         break;
2284       case HAL_OSPI_RX_CPLT_CB_ID :
2285         hospi->RxCpltCallback = HAL_OSPI_RxCpltCallback;
2286         break;
2287       case HAL_OSPI_TX_CPLT_CB_ID :
2288         hospi->TxCpltCallback = HAL_OSPI_TxCpltCallback;
2289         break;
2290       case HAL_OSPI_RX_HALF_CPLT_CB_ID :
2291         hospi->RxHalfCpltCallback = HAL_OSPI_RxHalfCpltCallback;
2292         break;
2293       case HAL_OSPI_TX_HALF_CPLT_CB_ID :
2294         hospi->TxHalfCpltCallback = HAL_OSPI_TxHalfCpltCallback;
2295         break;
2296       case HAL_OSPI_STATUS_MATCH_CB_ID :
2297         hospi->StatusMatchCallback = HAL_OSPI_StatusMatchCallback;
2298         break;
2299       case HAL_OSPI_TIMEOUT_CB_ID :
2300         hospi->TimeOutCallback = HAL_OSPI_TimeOutCallback;
2301         break;
2302       case HAL_OSPI_MSP_INIT_CB_ID :
2303         hospi->MspInitCallback = HAL_OSPI_MspInit;
2304         break;
2305       case HAL_OSPI_MSP_DEINIT_CB_ID :
2306         hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
2307         break;
2308       default :
2309         /* Update the error code */
2310         hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2311         /* update return status */
2312         status =  HAL_ERROR;
2313         break;
2314     }
2315   }
2316   else if (hospi->State == HAL_OSPI_STATE_RESET)
2317   {
2318     switch (CallbackID)
2319     {
2320       case HAL_OSPI_MSP_INIT_CB_ID :
2321         hospi->MspInitCallback = HAL_OSPI_MspInit;
2322         break;
2323       case HAL_OSPI_MSP_DEINIT_CB_ID :
2324         hospi->MspDeInitCallback = HAL_OSPI_MspDeInit;
2325         break;
2326       default :
2327         /* Update the error code */
2328         hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2329         /* update return status */
2330         status =  HAL_ERROR;
2331         break;
2332     }
2333   }
2334   else
2335   {
2336     /* Update the error code */
2337     hospi->ErrorCode |= HAL_OSPI_ERROR_INVALID_CALLBACK;
2338     /* update return status */
2339     status =  HAL_ERROR;
2340   }
2341 
2342   return status;
2343 }
2344 #endif /* defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) */
2345 
2346 /**
2347   * @}
2348   */
2349 
2350 /** @defgroup OSPI_Exported_Functions_Group3 Peripheral Control and State functions
2351   *  @brief   OSPI control and State functions
2352   *
2353 @verbatim
2354  ===============================================================================
2355                   ##### Peripheral Control and State functions #####
2356  ===============================================================================
2357     [..]
2358     This subsection provides a set of functions allowing to :
2359       (+) Check in run-time the state of the driver.
2360       (+) Check the error code set during last operation.
2361       (+) Abort any operation.
2362       (+) Manage the Fifo threshold.
2363       (+) Configure the timeout duration used in the driver.
2364 
2365 @endverbatim
2366   * @{
2367   */
2368 
2369 /**
2370   * @brief  Abort the current transmission.
2371   * @param  hospi : OSPI handle
2372   * @retval HAL status
2373   */
HAL_OSPI_Abort(OSPI_HandleTypeDef * hospi)2374 HAL_StatusTypeDef HAL_OSPI_Abort(OSPI_HandleTypeDef *hospi)
2375 {
2376   HAL_StatusTypeDef status = HAL_OK;
2377   uint32_t state;
2378   uint32_t tickstart = HAL_GetTick();
2379 
2380   /* Check if the state is in one of the busy or configured states */
2381   state = hospi->State;
2382   if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
2383   {
2384     /* Check if the DMA is enabled */
2385     if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
2386     {
2387       /* Disable the DMA transfer on the OctoSPI side */
2388       CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2389 
2390       /* Disable the DMA transfer on the DMA side */
2391       status = HAL_DMA_Abort(hospi->hdma);
2392       if (status != HAL_OK)
2393       {
2394         hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
2395       }
2396     }
2397 
2398     if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2399     {
2400       /* Perform an abort of the OctoSPI */
2401       SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2402 
2403       /* Wait until the transfer complete flag is set to go back in idle state */
2404       status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_TC, SET, tickstart, hospi->Timeout);
2405 
2406       if (status == HAL_OK)
2407       {
2408         /* Clear transfer complete flag */
2409         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2410 
2411         /* Wait until the busy flag is reset to go back in idle state */
2412         status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, hospi->Timeout);
2413 
2414         if (status == HAL_OK)
2415         {
2416           /* Update state */
2417           hospi->State = HAL_OSPI_STATE_READY;
2418         }
2419       }
2420     }
2421     else
2422     {
2423       /* Update state */
2424       hospi->State = HAL_OSPI_STATE_READY;
2425     }
2426   }
2427   else
2428   {
2429     status = HAL_ERROR;
2430     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2431   }
2432 
2433   /* Return function status */
2434   return status;
2435 }
2436 
2437 /**
2438   * @brief  Abort the current transmission (non-blocking function)
2439   * @param  hospi : OSPI handle
2440   * @retval HAL status
2441   */
HAL_OSPI_Abort_IT(OSPI_HandleTypeDef * hospi)2442 HAL_StatusTypeDef HAL_OSPI_Abort_IT(OSPI_HandleTypeDef *hospi)
2443 {
2444   HAL_StatusTypeDef status = HAL_OK;
2445   uint32_t state;
2446 
2447   /* Check if the state is in one of the busy or configured states */
2448   state = hospi->State;
2449   if (((state & OSPI_BUSY_STATE_MASK) != 0U) || ((state & OSPI_CFG_STATE_MASK) != 0U))
2450   {
2451     /* Disable all interrupts */
2452     __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));
2453 
2454     /* Update state */
2455     hospi->State = HAL_OSPI_STATE_ABORT;
2456 
2457     /* Check if the DMA is enabled */
2458     if ((hospi->Instance->CR & OCTOSPI_CR_DMAEN) != 0U)
2459     {
2460       /* Disable the DMA transfer on the OctoSPI side */
2461       CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2462 
2463       /* Disable the DMA transfer on the DMA side */
2464       hospi->hdma->XferAbortCallback = OSPI_DMAAbortCplt;
2465       if (HAL_DMA_Abort_IT(hospi->hdma) != HAL_OK)
2466       {
2467         /* Update state */
2468         hospi->State = HAL_OSPI_STATE_READY;
2469 
2470         /* Abort callback */
2471 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2472         hospi->AbortCpltCallback(hospi);
2473 #else
2474         HAL_OSPI_AbortCpltCallback(hospi);
2475 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)*/
2476       }
2477     }
2478     else
2479     {
2480       if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2481       {
2482         /* Clear transfer complete flag */
2483         __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2484 
2485         /* Enable the transfer complete interrupts */
2486         __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2487 
2488         /* Perform an abort of the OctoSPI */
2489         SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2490       }
2491       else
2492       {
2493         /* Update state */
2494         hospi->State = HAL_OSPI_STATE_READY;
2495 
2496         /* Abort callback */
2497 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2498         hospi->AbortCpltCallback(hospi);
2499 #else
2500         HAL_OSPI_AbortCpltCallback(hospi);
2501 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) */
2502       }
2503     }
2504   }
2505   else
2506   {
2507     status = HAL_ERROR;
2508     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2509   }
2510 
2511   /* Return function status */
2512   return status;
2513 }
2514 
2515 /** @brief  Set OSPI Fifo threshold.
2516   * @param  hospi     : OSPI handle.
2517   * @param  Threshold : Threshold of the Fifo.
2518   * @retval HAL status
2519   */
HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef * hospi,uint32_t Threshold)2520 HAL_StatusTypeDef HAL_OSPI_SetFifoThreshold(OSPI_HandleTypeDef *hospi, uint32_t Threshold)
2521 {
2522   HAL_StatusTypeDef status = HAL_OK;
2523 
2524   /* Check the state */
2525   if ((hospi->State & OSPI_BUSY_STATE_MASK) == 0U)
2526   {
2527     /* Synchronize initialization structure with the new fifo threshold value */
2528     hospi->Init.FifoThreshold = Threshold;
2529 
2530     /* Configure new fifo threshold */
2531     MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FTHRES, ((hospi->Init.FifoThreshold - 1U) << OCTOSPI_CR_FTHRES_Pos));
2532 
2533   }
2534   else
2535   {
2536     status = HAL_ERROR;
2537     hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
2538   }
2539 
2540   /* Return function status */
2541   return status;
2542 }
2543 
2544 /** @brief  Get OSPI Fifo threshold.
2545   * @param  hospi : OSPI handle.
2546   * @retval Fifo threshold
2547   */
HAL_OSPI_GetFifoThreshold(const OSPI_HandleTypeDef * hospi)2548 uint32_t HAL_OSPI_GetFifoThreshold(const OSPI_HandleTypeDef *hospi)
2549 {
2550   return ((READ_BIT(hospi->Instance->CR, OCTOSPI_CR_FTHRES) >> OCTOSPI_CR_FTHRES_Pos) + 1U);
2551 }
2552 
2553 /** @brief Set OSPI timeout.
2554   * @param  hospi   : OSPI handle.
2555   * @param  Timeout : Timeout for the memory access.
2556   * @retval None
2557   */
HAL_OSPI_SetTimeout(OSPI_HandleTypeDef * hospi,uint32_t Timeout)2558 HAL_StatusTypeDef HAL_OSPI_SetTimeout(OSPI_HandleTypeDef *hospi, uint32_t Timeout)
2559 {
2560   hospi->Timeout = Timeout;
2561   return HAL_OK;
2562 }
2563 
2564 /**
2565   * @brief  Return the OSPI error code.
2566   * @param  hospi : OSPI handle
2567   * @retval OSPI Error Code
2568   */
HAL_OSPI_GetError(const OSPI_HandleTypeDef * hospi)2569 uint32_t HAL_OSPI_GetError(const OSPI_HandleTypeDef *hospi)
2570 {
2571   return hospi->ErrorCode;
2572 }
2573 
2574 /**
2575   * @brief  Return the OSPI handle state.
2576   * @param  hospi : OSPI handle
2577   * @retval HAL state
2578   */
HAL_OSPI_GetState(const OSPI_HandleTypeDef * hospi)2579 uint32_t HAL_OSPI_GetState(const OSPI_HandleTypeDef *hospi)
2580 {
2581   /* Return OSPI handle state */
2582   return hospi->State;
2583 }
2584 
2585 /**
2586   * @}
2587   */
2588 
2589 #if     defined (OCTOSPIM)
2590 /** @defgroup OSPI_Exported_Functions_Group4 IO Manager configuration function
2591   *  @brief   OSPI IO Manager configuration function
2592   *
2593 @verbatim
2594  ===============================================================================
2595                   ##### IO Manager configuration function #####
2596  ===============================================================================
2597     [..]
2598     This subsection provides a set of functions allowing to :
2599       (+) Configure the IO manager.
2600 
2601 @endverbatim
2602   * @{
2603   */
2604 
2605 /**
2606   * @brief  Configure the OctoSPI IO manager.
2607   * @param  hospi   : OSPI handle
2608   * @param  cfg     : Configuration of the IO Manager for the instance
2609   * @param  Timeout : Timeout duration
2610   * @retval HAL status
2611   */
HAL_OSPIM_Config(OSPI_HandleTypeDef * hospi,OSPIM_CfgTypeDef * cfg,uint32_t Timeout)2612 HAL_StatusTypeDef HAL_OSPIM_Config(OSPI_HandleTypeDef *hospi, OSPIM_CfgTypeDef *cfg, uint32_t Timeout)
2613 {
2614   HAL_StatusTypeDef status = HAL_OK;
2615   uint32_t instance;
2616   uint8_t index;
2617   uint8_t ospi_enabled = 0U;
2618   uint8_t other_instance;
2619   OSPIM_CfgTypeDef IOM_cfg[OSPI_NB_INSTANCE];
2620 
2621   /* Prevent unused argument(s) compilation warning */
2622   UNUSED(Timeout);
2623 
2624   /* Check the parameters of the OctoSPI IO Manager configuration structure */
2625   assert_param(IS_OSPIM_PORT(cfg->ClkPort));
2626   assert_param(IS_OSPIM_DQS_PORT(cfg->DQSPort));
2627   assert_param(IS_OSPIM_PORT(cfg->NCSPort));
2628   assert_param(IS_OSPIM_IO_PORT(cfg->IOLowPort));
2629   assert_param(IS_OSPIM_IO_PORT(cfg->IOHighPort));
2630 
2631   if (hospi->Instance == (OCTOSPI_TypeDef *)OCTOSPI1)
2632   {
2633     instance = 0U;
2634     other_instance = 1U;
2635   }
2636   else
2637   {
2638     instance = 1U;
2639     other_instance = 0U;
2640   }
2641 
2642   /**************** Get current configuration of the instances ****************/
2643   for (index = 0U; index < OSPI_NB_INSTANCE; index++)
2644   {
2645     if (OSPIM_GetConfig(index + 1U, &(IOM_cfg[index])) != HAL_OK)
2646     {
2647       status = HAL_ERROR;
2648       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
2649     }
2650   }
2651 
2652   if (status == HAL_OK)
2653   {
2654     /********** Disable both OctoSPI to configure OctoSPI IO Manager **********/
2655     if ((OCTOSPI1->CR & OCTOSPI_CR_EN) != 0U)
2656     {
2657       CLEAR_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
2658       ospi_enabled |= 0x1U;
2659     }
2660     if ((OCTOSPI2->CR & OCTOSPI_CR_EN) != 0U)
2661     {
2662       CLEAR_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
2663       ospi_enabled |= 0x2U;
2664     }
2665 
2666     /***************** Deactivation of previous configuration *****************/
2667     CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].NCSPort - 1U)], OCTOSPIM_PCR_NCSEN);
2668     if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U)
2669     {
2670       /* De-multiplexing should be performed */
2671       CLEAR_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN);
2672 
2673       if (other_instance == 1U)
2674       {
2675         SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort - 1U)], OCTOSPIM_PCR_CLKSRC);
2676         if (IOM_cfg[other_instance].DQSPort != 0U)
2677         {
2678           SET_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort - 1U)], OCTOSPIM_PCR_DQSSRC);
2679         }
2680         if (IOM_cfg[other_instance].IOLowPort != HAL_OSPIM_IOPORT_NONE)
2681         {
2682           SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort - 1U)& OSPI_IOM_PORT_MASK)], \
2683                   OCTOSPIM_PCR_IOLSRC_1);
2684         }
2685         if (IOM_cfg[other_instance].IOHighPort != HAL_OSPIM_IOPORT_NONE)
2686         {
2687           SET_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort - 1U)& OSPI_IOM_PORT_MASK)], \
2688                   OCTOSPIM_PCR_IOHSRC_1);
2689         }
2690       }
2691     }
2692     else
2693     {
2694       if (IOM_cfg[instance].ClkPort != 0U)
2695       {
2696         CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].ClkPort - 1U)], OCTOSPIM_PCR_CLKEN);
2697         if (IOM_cfg[instance].DQSPort != 0U)
2698         {
2699           CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[instance].DQSPort - 1U)], OCTOSPIM_PCR_DQSEN);
2700         }
2701         if (IOM_cfg[instance].IOLowPort != HAL_OSPIM_IOPORT_NONE)
2702         {
2703           CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOLowPort - 1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOLEN);
2704         }
2705         if (IOM_cfg[instance].IOHighPort != HAL_OSPIM_IOPORT_NONE)
2706         {
2707           CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[instance].IOHighPort - 1U)& OSPI_IOM_PORT_MASK)], OCTOSPIM_PCR_IOHEN);
2708         }
2709       }
2710     }
2711 
2712     /********************* Deactivation of other instance *********************/
2713     if ((cfg->ClkPort == IOM_cfg[other_instance].ClkPort) || (cfg->NCSPort == IOM_cfg[other_instance].NCSPort) ||
2714         ((cfg->DQSPort == IOM_cfg[other_instance].DQSPort) && (cfg->DQSPort != 0U)) ||
2715         (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) ||
2716         (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort))
2717     {
2718       if ((cfg->ClkPort   == IOM_cfg[other_instance].ClkPort)   &&
2719           (cfg->DQSPort    == IOM_cfg[other_instance].DQSPort)  &&
2720           (cfg->IOLowPort == IOM_cfg[other_instance].IOLowPort) &&
2721           (cfg->IOHighPort == IOM_cfg[other_instance].IOHighPort))
2722       {
2723         /* Multiplexing should be performed */
2724         SET_BIT(OCTOSPIM->CR, OCTOSPIM_CR_MUXEN);
2725       }
2726       else
2727       {
2728         CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].ClkPort - 1U)], OCTOSPIM_PCR_CLKEN);
2729         if (IOM_cfg[other_instance].DQSPort != 0U)
2730         {
2731           CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].DQSPort - 1U)], OCTOSPIM_PCR_DQSEN);
2732         }
2733         CLEAR_BIT(OCTOSPIM->PCR[(IOM_cfg[other_instance].NCSPort - 1U)], OCTOSPIM_PCR_NCSEN);
2734         if (IOM_cfg[other_instance].IOLowPort != HAL_OSPIM_IOPORT_NONE)
2735         {
2736           CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOLowPort - 1U)& OSPI_IOM_PORT_MASK)],
2737                     OCTOSPIM_PCR_IOLEN);
2738         }
2739         if (IOM_cfg[other_instance].IOHighPort != HAL_OSPIM_IOPORT_NONE)
2740         {
2741           CLEAR_BIT(OCTOSPIM->PCR[((IOM_cfg[other_instance].IOHighPort - 1U)& OSPI_IOM_PORT_MASK)],
2742                     OCTOSPIM_PCR_IOHEN);
2743         }
2744       }
2745     }
2746 
2747     /******************** Activation of new configuration *********************/
2748     MODIFY_REG(OCTOSPIM->PCR[(cfg->NCSPort - 1U)], (OCTOSPIM_PCR_NCSEN | OCTOSPIM_PCR_NCSSRC),
2749                (OCTOSPIM_PCR_NCSEN | (instance << OCTOSPIM_PCR_NCSSRC_Pos)));
2750 
2751     if (((cfg->Req2AckTime) >= 1U) && ((cfg->Req2AckTime) <= 256U))
2752     {
2753       if ((cfg->Req2AckTime - 1U) > ((OCTOSPIM->CR & OCTOSPIM_CR_REQ2ACK_TIME) >> OCTOSPIM_CR_REQ2ACK_TIME_Pos))
2754       {
2755         MODIFY_REG(OCTOSPIM->CR, OCTOSPIM_CR_REQ2ACK_TIME, ((cfg->Req2AckTime - 1U) << OCTOSPIM_CR_REQ2ACK_TIME_Pos));
2756       }
2757       else
2758       {
2759         /* Nothing to do */
2760       }
2761     }
2762 
2763     if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) != 0U)
2764     {
2765       MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort - 1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC), OCTOSPIM_PCR_CLKEN);
2766       if (cfg->DQSPort != 0U)
2767       {
2768         MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort - 1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC), OCTOSPIM_PCR_DQSEN);
2769       }
2770 
2771       if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U)
2772       {
2773         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort - 1U)& OSPI_IOM_PORT_MASK)],
2774                    (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), OCTOSPIM_PCR_IOLEN);
2775       }
2776       else if (cfg->IOLowPort != HAL_OSPIM_IOPORT_NONE)
2777       {
2778         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort - 1U)& OSPI_IOM_PORT_MASK)],
2779                    (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), OCTOSPIM_PCR_IOHEN);
2780       }
2781       else
2782       {
2783         /* Nothing to do */
2784       }
2785 
2786       if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U)
2787       {
2788         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort - 1U)& OSPI_IOM_PORT_MASK)],
2789                    (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC), (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0));
2790       }
2791       else if (cfg->IOHighPort != HAL_OSPIM_IOPORT_NONE)
2792       {
2793         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort - 1U)& OSPI_IOM_PORT_MASK)],
2794                    (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC), (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0));
2795       }
2796       else
2797       {
2798         /* Nothing to do */
2799       }
2800     }
2801     else
2802     {
2803       MODIFY_REG(OCTOSPIM->PCR[(cfg->ClkPort - 1U)], (OCTOSPIM_PCR_CLKEN | OCTOSPIM_PCR_CLKSRC),
2804                  (OCTOSPIM_PCR_CLKEN | (instance << OCTOSPIM_PCR_CLKSRC_Pos)));
2805       if (cfg->DQSPort != 0U)
2806       {
2807         MODIFY_REG(OCTOSPIM->PCR[(cfg->DQSPort - 1U)], (OCTOSPIM_PCR_DQSEN | OCTOSPIM_PCR_DQSSRC),
2808                    (OCTOSPIM_PCR_DQSEN | (instance << OCTOSPIM_PCR_DQSSRC_Pos)));
2809       }
2810 
2811       if ((cfg->IOLowPort & OCTOSPIM_PCR_IOLEN) != 0U)
2812       {
2813         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort - 1U)& OSPI_IOM_PORT_MASK)],
2814                    (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
2815                    (OCTOSPIM_PCR_IOLEN | (instance << (OCTOSPIM_PCR_IOLSRC_Pos + 1U))));
2816       }
2817       else if (cfg->IOLowPort != HAL_OSPIM_IOPORT_NONE)
2818       {
2819         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOLowPort - 1U)& OSPI_IOM_PORT_MASK)],
2820                    (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
2821                    (OCTOSPIM_PCR_IOHEN | (instance << (OCTOSPIM_PCR_IOHSRC_Pos + 1U))));
2822       }
2823       else
2824       {
2825         /* Nothing to do */
2826       }
2827 
2828       if ((cfg->IOHighPort & OCTOSPIM_PCR_IOLEN) != 0U)
2829       {
2830         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort - 1U)& OSPI_IOM_PORT_MASK)],
2831                    (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC),
2832                    (OCTOSPIM_PCR_IOLEN | OCTOSPIM_PCR_IOLSRC_0 | (instance << (OCTOSPIM_PCR_IOLSRC_Pos + 1U))));
2833       }
2834       else if (cfg->IOHighPort != HAL_OSPIM_IOPORT_NONE)
2835       {
2836         MODIFY_REG(OCTOSPIM->PCR[((cfg->IOHighPort - 1U)& OSPI_IOM_PORT_MASK)],
2837                    (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC),
2838                    (OCTOSPIM_PCR_IOHEN | OCTOSPIM_PCR_IOHSRC_0 | (instance << (OCTOSPIM_PCR_IOHSRC_Pos + 1U))));
2839       }
2840       else
2841       {
2842         /* Nothing to do */
2843       }
2844     }
2845 
2846     /******* Re-enable both OctoSPI after configure OctoSPI IO Manager ********/
2847     if ((ospi_enabled & 0x1U) != 0U)
2848     {
2849       SET_BIT(OCTOSPI1->CR, OCTOSPI_CR_EN);
2850     }
2851     if ((ospi_enabled & 0x2U) != 0U)
2852     {
2853       SET_BIT(OCTOSPI2->CR, OCTOSPI_CR_EN);
2854     }
2855   }
2856 
2857   /* Return function status */
2858   return status;
2859 }
2860 
2861 /**
2862   * @}
2863   */
2864 #endif /* OCTOSPIM */
2865 
2866 /**
2867   @cond 0
2868   */
2869 /**
2870   * @brief  DMA OSPI process complete callback.
2871   * @param  hdma : DMA handle
2872   * @retval None
2873   */
OSPI_DMACplt(DMA_HandleTypeDef * hdma)2874 static void OSPI_DMACplt(DMA_HandleTypeDef *hdma)
2875 {
2876   OSPI_HandleTypeDef *hospi = (OSPI_HandleTypeDef *)(hdma->Parent);
2877   hospi->XferCount = 0;
2878 
2879   /* Disable the DMA transfer on the OctoSPI side */
2880   CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2881 
2882   /* Disable the DMA channel */
2883   __HAL_DMA_DISABLE(hdma);
2884 
2885   /* Enable the OSPI transfer complete Interrupt */
2886   __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2887 }
2888 
2889 /**
2890   * @brief  DMA OSPI process half complete callback.
2891   * @param  hdma : DMA handle
2892   * @retval None
2893   */
OSPI_DMAHalfCplt(DMA_HandleTypeDef * hdma)2894 static void OSPI_DMAHalfCplt(DMA_HandleTypeDef *hdma)
2895 {
2896   OSPI_HandleTypeDef *hospi = (OSPI_HandleTypeDef *)(hdma->Parent);
2897   hospi->XferCount = (hospi->XferCount >> 1);
2898 
2899   if (hospi->State == HAL_OSPI_STATE_BUSY_RX)
2900   {
2901 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2902     hospi->RxHalfCpltCallback(hospi);
2903 #else
2904     HAL_OSPI_RxHalfCpltCallback(hospi);
2905 #endif /*(USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) */
2906   }
2907   else
2908   {
2909 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2910     hospi->TxHalfCpltCallback(hospi);
2911 #else
2912     HAL_OSPI_TxHalfCpltCallback(hospi);
2913 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)*/
2914   }
2915 }
2916 
2917 /**
2918   * @brief  DMA OSPI communication error callback.
2919   * @param  hdma : DMA handle
2920   * @retval None
2921   */
OSPI_DMAError(DMA_HandleTypeDef * hdma)2922 static void OSPI_DMAError(DMA_HandleTypeDef *hdma)
2923 {
2924   OSPI_HandleTypeDef *hospi = (OSPI_HandleTypeDef *)(hdma->Parent);
2925   hospi->XferCount = 0;
2926   hospi->ErrorCode = HAL_OSPI_ERROR_DMA;
2927 
2928   /* Disable the DMA transfer on the OctoSPI side */
2929   CLEAR_BIT(hospi->Instance->CR, OCTOSPI_CR_DMAEN);
2930 
2931   /* Abort the OctoSPI */
2932   if (HAL_OSPI_Abort_IT(hospi) != HAL_OK)
2933   {
2934     /* Disable the interrupts */
2935     __HAL_OSPI_DISABLE_IT(hospi, HAL_OSPI_IT_TC | HAL_OSPI_IT_FT | HAL_OSPI_IT_TE);
2936 
2937     /* Update state */
2938     hospi->State = HAL_OSPI_STATE_READY;
2939 
2940     /* Error callback */
2941 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2942     hospi->ErrorCallback(hospi);
2943 #else
2944     HAL_OSPI_ErrorCallback(hospi);
2945 #endif /*(USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) */
2946   }
2947 }
2948 
2949 /**
2950   * @brief  DMA OSPI abort complete callback.
2951   * @param  hdma : DMA handle
2952   * @retval None
2953   */
OSPI_DMAAbortCplt(DMA_HandleTypeDef * hdma)2954 static void OSPI_DMAAbortCplt(DMA_HandleTypeDef *hdma)
2955 {
2956   OSPI_HandleTypeDef *hospi = (OSPI_HandleTypeDef *)(hdma->Parent);
2957   hospi->XferCount = 0;
2958 
2959   /* Check the state */
2960   if (hospi->State == HAL_OSPI_STATE_ABORT)
2961   {
2962     /* DMA abort called by OctoSPI abort */
2963     if (__HAL_OSPI_GET_FLAG(hospi, HAL_OSPI_FLAG_BUSY) != RESET)
2964     {
2965       /* Clear transfer complete flag */
2966       __HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_TC);
2967 
2968       /* Enable the transfer complete interrupts */
2969       __HAL_OSPI_ENABLE_IT(hospi, HAL_OSPI_IT_TC);
2970 
2971       /* Perform an abort of the OctoSPI */
2972       SET_BIT(hospi->Instance->CR, OCTOSPI_CR_ABORT);
2973     }
2974     else
2975     {
2976       /* Update state */
2977       hospi->State = HAL_OSPI_STATE_READY;
2978 
2979       /* Abort callback */
2980 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2981       hospi->AbortCpltCallback(hospi);
2982 #else
2983       HAL_OSPI_AbortCpltCallback(hospi);
2984 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U) */
2985     }
2986   }
2987   else
2988   {
2989     /* DMA abort called due to a transfer error interrupt */
2990     /* Update state */
2991     hospi->State = HAL_OSPI_STATE_READY;
2992 
2993     /* Error callback */
2994 #if defined (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)
2995     hospi->ErrorCallback(hospi);
2996 #else
2997     HAL_OSPI_ErrorCallback(hospi);
2998 #endif /* (USE_HAL_OSPI_REGISTER_CALLBACKS) && (USE_HAL_OSPI_REGISTER_CALLBACKS == 1U)*/
2999   }
3000 }
3001 
3002 /**
3003   * @brief  Wait for a flag state until timeout.
3004   * @param  hospi     : OSPI handle
3005   * @param  Flag      : Flag checked
3006   * @param  State     : Value of the flag expected
3007   * @param  Timeout   : Duration of the timeout
3008   * @param  Tickstart : Tick start value
3009   * @retval HAL status
3010   */
OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef * hospi,uint32_t Flag,FlagStatus State,uint32_t Tickstart,uint32_t Timeout)3011 static HAL_StatusTypeDef OSPI_WaitFlagStateUntilTimeout(OSPI_HandleTypeDef *hospi, uint32_t Flag,
3012                                                         FlagStatus State, uint32_t Tickstart, uint32_t Timeout)
3013 {
3014   /* Wait until flag is in expected state */
3015   while ((__HAL_OSPI_GET_FLAG(hospi, Flag)) != State)
3016   {
3017     /* Check for the Timeout */
3018     if (Timeout != HAL_MAX_DELAY)
3019     {
3020       if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
3021       {
3022         /* New check to avoid false timeout detection in case of preemption */
3023         if ((hospi->Instance->SR & Flag) != (uint32_t)State)
3024         {
3025           hospi->State     = HAL_OSPI_STATE_ERROR;
3026           hospi->ErrorCode |= HAL_OSPI_ERROR_TIMEOUT;
3027 
3028           return HAL_ERROR;
3029         }
3030       }
3031     }
3032   }
3033   return HAL_OK;
3034 }
3035 
3036 /**
3037   * @brief  Configure the registers for the regular command mode.
3038   * @param  hospi : OSPI handle
3039   * @param  cmd   : structure that contains the command configuration information
3040   * @retval HAL status
3041   */
OSPI_ConfigCmd(OSPI_HandleTypeDef * hospi,OSPI_RegularCmdTypeDef * cmd)3042 static HAL_StatusTypeDef OSPI_ConfigCmd(OSPI_HandleTypeDef *hospi, OSPI_RegularCmdTypeDef *cmd)
3043 {
3044   HAL_StatusTypeDef status = HAL_OK;
3045   __IO uint32_t *ccr_reg;
3046   __IO uint32_t *tcr_reg;
3047   __IO uint32_t *ir_reg;
3048   __IO uint32_t *abr_reg;
3049 
3050   /* Re-initialize the value of the functional mode */
3051   MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_FMODE, 0U);
3052 
3053   /* Configure the flash ID */
3054   if (hospi->Init.DualQuad == HAL_OSPI_DUALQUAD_DISABLE)
3055   {
3056     MODIFY_REG(hospi->Instance->CR, OCTOSPI_CR_MSEL, cmd->FlashId);
3057   }
3058 
3059   if (cmd->OperationType == HAL_OSPI_OPTYPE_WRITE_CFG)
3060   {
3061     ccr_reg = &(hospi->Instance->WCCR);
3062     tcr_reg = &(hospi->Instance->WTCR);
3063     ir_reg  = &(hospi->Instance->WIR);
3064     abr_reg = &(hospi->Instance->WABR);
3065   }
3066   else if (cmd->OperationType == HAL_OSPI_OPTYPE_WRAP_CFG)
3067   {
3068     ccr_reg = &(hospi->Instance->WPCCR);
3069     tcr_reg = &(hospi->Instance->WPTCR);
3070     ir_reg  = &(hospi->Instance->WPIR);
3071     abr_reg = &(hospi->Instance->WPABR);
3072   }
3073   else
3074   {
3075     ccr_reg = &(hospi->Instance->CCR);
3076     tcr_reg = &(hospi->Instance->TCR);
3077     ir_reg  = &(hospi->Instance->IR);
3078     abr_reg = &(hospi->Instance->ABR);
3079   }
3080 
3081   /* Configure the CCR register with DQS and SIOO modes */
3082   *ccr_reg = (cmd->DQSMode | cmd->SIOOMode);
3083 
3084   if (cmd->AlternateBytesMode != HAL_OSPI_ALTERNATE_BYTES_NONE)
3085   {
3086     /* Configure the ABR register with alternate bytes value */
3087     *abr_reg = cmd->AlternateBytes;
3088 
3089     /* Configure the CCR register with alternate bytes communication parameters */
3090     MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ABMODE | OCTOSPI_CCR_ABDTR | OCTOSPI_CCR_ABSIZE),
3091                (cmd->AlternateBytesMode | cmd->AlternateBytesDtrMode | cmd->AlternateBytesSize));
3092   }
3093 
3094   /* Configure the TCR register with the number of dummy cycles */
3095   MODIFY_REG((*tcr_reg), OCTOSPI_TCR_DCYC, cmd->DummyCycles);
3096 
3097   if (cmd->DataMode != HAL_OSPI_DATA_NONE)
3098   {
3099     if (cmd->OperationType == HAL_OSPI_OPTYPE_COMMON_CFG)
3100     {
3101       /* Configure the DLR register with the number of data */
3102       hospi->Instance->DLR = (cmd->NbData - 1U);
3103     }
3104   }
3105 
3106   if (cmd->InstructionMode != HAL_OSPI_INSTRUCTION_NONE)
3107   {
3108     if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
3109     {
3110       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
3111       {
3112         /* ---- Command with instruction, address and data ---- */
3113 
3114         /* Configure the CCR register with all communication parameters */
3115         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE  | OCTOSPI_CCR_IDTR  | OCTOSPI_CCR_ISIZE  |
3116                                 OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
3117                                 OCTOSPI_CCR_DMODE  | OCTOSPI_CCR_DDTR),
3118                    (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
3119                     cmd->AddressMode     | cmd->AddressDtrMode     | cmd->AddressSize     |
3120                     cmd->DataMode        | cmd->DataDtrMode));
3121       }
3122       else
3123       {
3124         /* ---- Command with instruction and address ---- */
3125 
3126         /* Configure the CCR register with all communication parameters */
3127         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE  | OCTOSPI_CCR_IDTR  | OCTOSPI_CCR_ISIZE  |
3128                                 OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
3129                    (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
3130                     cmd->AddressMode     | cmd->AddressDtrMode     | cmd->AddressSize));
3131 
3132         /* The DHQC bit is linked with DDTR bit which should be activated */
3133         if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
3134             (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
3135         {
3136           MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
3137         }
3138       }
3139 
3140       /* Configure the IR register with the instruction value */
3141       *ir_reg = cmd->Instruction;
3142 
3143       /* Configure the AR register with the address value */
3144       hospi->Instance->AR = cmd->Address;
3145     }
3146     else
3147     {
3148       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
3149       {
3150         /* ---- Command with instruction and data ---- */
3151 
3152         /* Configure the CCR register with all communication parameters */
3153         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE |
3154                                 OCTOSPI_CCR_DMODE | OCTOSPI_CCR_DDTR),
3155                    (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize |
3156                     cmd->DataMode        | cmd->DataDtrMode));
3157       }
3158       else
3159       {
3160         /* ---- Command with only instruction ---- */
3161 
3162         /* Configure the CCR register with all communication parameters */
3163         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_IMODE | OCTOSPI_CCR_IDTR | OCTOSPI_CCR_ISIZE),
3164                    (cmd->InstructionMode | cmd->InstructionDtrMode | cmd->InstructionSize));
3165 
3166         /* The DHQC bit is linked with DDTR bit which should be activated */
3167         if ((hospi->Init.DelayHoldQuarterCycle == HAL_OSPI_DHQC_ENABLE) &&
3168             (cmd->InstructionDtrMode == HAL_OSPI_INSTRUCTION_DTR_ENABLE))
3169         {
3170           MODIFY_REG((*ccr_reg), OCTOSPI_CCR_DDTR, HAL_OSPI_DATA_DTR_ENABLE);
3171         }
3172       }
3173 
3174       /* Configure the IR register with the instruction value */
3175       *ir_reg = cmd->Instruction;
3176 
3177     }
3178   }
3179   else
3180   {
3181     if (cmd->AddressMode != HAL_OSPI_ADDRESS_NONE)
3182     {
3183       if (cmd->DataMode != HAL_OSPI_DATA_NONE)
3184       {
3185         /* ---- Command with address and data ---- */
3186 
3187         /* Configure the CCR register with all communication parameters */
3188         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE |
3189                                 OCTOSPI_CCR_DMODE  | OCTOSPI_CCR_DDTR),
3190                    (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize | cmd->DataMode |
3191                     cmd->DataDtrMode));
3192       }
3193       else
3194       {
3195         /* ---- Command with only address ---- */
3196 
3197         /* Configure the CCR register with all communication parameters */
3198         MODIFY_REG((*ccr_reg), (OCTOSPI_CCR_ADMODE | OCTOSPI_CCR_ADDTR | OCTOSPI_CCR_ADSIZE),
3199                    (cmd->AddressMode | cmd->AddressDtrMode | cmd->AddressSize));
3200       }
3201 
3202       /* Configure the AR register with the instruction value */
3203       hospi->Instance->AR = cmd->Address;
3204     }
3205     else
3206     {
3207       /* ---- Invalid command configuration (no instruction, no address) ---- */
3208       status = HAL_ERROR;
3209       hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_PARAM;
3210     }
3211   }
3212 
3213   /* Return function status */
3214   return status;
3215 }
3216 
3217 #if     defined (OCTOSPIM)
3218 /**
3219   * @brief  Get the current IOM configuration for an OctoSPI instance.
3220   * @param  instance_nb : number of the instance
3221   * @param  cfg         : configuration of the IO Manager for the instance
3222   * @retval HAL status
3223   */
OSPIM_GetConfig(uint8_t instance_nb,OSPIM_CfgTypeDef * cfg)3224 static HAL_StatusTypeDef OSPIM_GetConfig(uint8_t instance_nb, OSPIM_CfgTypeDef *cfg)
3225 {
3226   HAL_StatusTypeDef status = HAL_OK;
3227   uint32_t reg;
3228   uint32_t value = 0U;
3229   uint32_t index;
3230 
3231   if ((instance_nb == 0U) || (instance_nb > OSPI_NB_INSTANCE) || (cfg == NULL))
3232   {
3233     /* Invalid parameter -> error returned */
3234     status = HAL_ERROR;
3235   }
3236   else
3237   {
3238     /* Initialize the structure */
3239     cfg->ClkPort    = 0U;
3240     cfg->DQSPort    = 0U;
3241     cfg->NCSPort    = 0U;
3242     cfg->IOLowPort  = 0U;
3243     cfg->IOHighPort = 0U;
3244 
3245     if (instance_nb == 2U)
3246     {
3247       if ((OCTOSPIM->CR & OCTOSPIM_CR_MUXEN) == 0U)
3248       {
3249         value = (OCTOSPIM_PCR_CLKSRC | OCTOSPIM_PCR_DQSSRC | OCTOSPIM_PCR_NCSSRC
3250                  | OCTOSPIM_PCR_IOLSRC_1 | OCTOSPIM_PCR_IOHSRC_1);
3251       }
3252       else
3253       {
3254         value = OCTOSPIM_PCR_NCSSRC;
3255       }
3256     }
3257 
3258     /* Get the information about the instance */
3259     for (index = 0U; index < OSPI_IOM_NB_PORTS; index ++)
3260     {
3261       reg = OCTOSPIM->PCR[index];
3262 
3263       if ((reg & OCTOSPIM_PCR_CLKEN) != 0U)
3264       {
3265         /* The clock is enabled on this port */
3266         if ((reg & OCTOSPIM_PCR_CLKSRC) == (value & OCTOSPIM_PCR_CLKSRC))
3267         {
3268           /* The clock correspond to the instance passed as parameter */
3269           cfg->ClkPort = index + 1U;
3270         }
3271       }
3272 
3273       if ((reg & OCTOSPIM_PCR_DQSEN) != 0U)
3274       {
3275         /* The DQS is enabled on this port */
3276         if ((reg & OCTOSPIM_PCR_DQSSRC) == (value & OCTOSPIM_PCR_DQSSRC))
3277         {
3278           /* The DQS correspond to the instance passed as parameter */
3279           cfg->DQSPort = index + 1U;
3280         }
3281       }
3282 
3283       if ((reg & OCTOSPIM_PCR_NCSEN) != 0U)
3284       {
3285         /* The nCS is enabled on this port */
3286         if ((reg & OCTOSPIM_PCR_NCSSRC) == (value & OCTOSPIM_PCR_NCSSRC))
3287         {
3288           /* The nCS correspond to the instance passed as parameter */
3289           cfg->NCSPort = index + 1U;
3290         }
3291       }
3292 
3293       if ((reg & OCTOSPIM_PCR_IOLEN) != 0U)
3294       {
3295         /* The IO Low is enabled on this port */
3296         if ((reg & OCTOSPIM_PCR_IOLSRC_1) == (value & OCTOSPIM_PCR_IOLSRC_1))
3297         {
3298           /* The IO Low correspond to the instance passed as parameter */
3299           if ((reg & OCTOSPIM_PCR_IOLSRC_0) == 0U)
3300           {
3301             cfg->IOLowPort = (OCTOSPIM_PCR_IOLEN | (index + 1U));
3302           }
3303           else
3304           {
3305             cfg->IOLowPort = (OCTOSPIM_PCR_IOHEN | (index + 1U));
3306           }
3307         }
3308       }
3309 
3310       if ((reg & OCTOSPIM_PCR_IOHEN) != 0U)
3311       {
3312         /* The IO High is enabled on this port */
3313         if ((reg & OCTOSPIM_PCR_IOHSRC_1) == (value & OCTOSPIM_PCR_IOHSRC_1))
3314         {
3315           /* The IO High correspond to the instance passed as parameter */
3316           if ((reg & OCTOSPIM_PCR_IOHSRC_0) == 0U)
3317           {
3318             cfg->IOHighPort = (OCTOSPIM_PCR_IOLEN | (index + 1U));
3319           }
3320           else
3321           {
3322             cfg->IOHighPort = (OCTOSPIM_PCR_IOHEN | (index + 1U));
3323           }
3324         }
3325       }
3326     }
3327   }
3328 
3329   /* Return function status */
3330   return status;
3331 }
3332 #endif /* OCTOSPIM */
3333 
3334 
3335 /** @defgroup OSPI_Exported_Functions_Group5 Delay Block function
3336   *  @brief   Delay block function
3337   *
3338 @verbatim
3339  ===============================================================================
3340                   ##### Delay Block function #####
3341  ===============================================================================
3342     [..]
3343     This subsection provides a set of functions allowing to :
3344       (+) Configure the delay block.
3345 
3346 @endverbatim
3347   * @{
3348   */
3349 
3350 /**
3351   * @brief  Set the Delay Block configuration.
3352   * @param  hospi   : OSPI handle.
3353   * @param  pdlyb_cfg: Pointer to DLYB configuration structure.
3354   * @retval HAL status.
3355   */
HAL_OSPI_DLYB_SetConfig(OSPI_HandleTypeDef * hospi,HAL_OSPI_DLYB_CfgTypeDef * pdlyb_cfg)3356 HAL_StatusTypeDef HAL_OSPI_DLYB_SetConfig(OSPI_HandleTypeDef *hospi, HAL_OSPI_DLYB_CfgTypeDef  *pdlyb_cfg)
3357 {
3358   HAL_StatusTypeDef status = HAL_ERROR;
3359 
3360   /* Enable OCTOSPI Free Running Clock (mandatory) */
3361   SET_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
3362 
3363   /* Update OCTOSPI state */
3364   hospi->State = HAL_OSPI_STATE_BUSY_CMD;
3365 
3366   if (hospi->Instance == OCTOSPI1)
3367   {
3368     /* Enable the DelayBlock */
3369     LL_DLYB_Enable(DLYB_OCTOSPI1);
3370 
3371     /* Set the Delay Block configuration */
3372     LL_DLYB_SetDelay(DLYB_OCTOSPI1, pdlyb_cfg);
3373     status = HAL_OK;
3374   }
3375 
3376 #if defined (OCTOSPI2)
3377   else if (hospi->Instance == OCTOSPI2)
3378   {
3379     /* Enable the DelayBlock */
3380     LL_DLYB_Enable(DLYB_OCTOSPI2);
3381 
3382     /* Set the Delay Block configuration */
3383     LL_DLYB_SetDelay(DLYB_OCTOSPI2, pdlyb_cfg);
3384     status = HAL_OK;
3385   }
3386 #endif /* OCTOSPI2 */
3387 
3388   else
3389   {
3390     /* Nothing to do */
3391   }
3392 
3393   /* Abort the current OCTOSPI operation if exist */
3394   (void)HAL_OSPI_Abort(hospi);
3395 
3396   /* Disable Free Running Clock */
3397   CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
3398 
3399   /* Return function status */
3400   return status;
3401 }
3402 
3403 /**
3404   * @brief  Get the Delay Block configuration.
3405   * @param  hospi   : OSPI handle.
3406   * @param  pdlyb_cfg: Pointer to DLYB configuration structure.
3407   * @retval HAL status.
3408   */
HAL_OSPI_DLYB_GetConfig(const OSPI_HandleTypeDef * hospi,HAL_OSPI_DLYB_CfgTypeDef * pdlyb_cfg)3409 HAL_StatusTypeDef HAL_OSPI_DLYB_GetConfig(const OSPI_HandleTypeDef *hospi, HAL_OSPI_DLYB_CfgTypeDef  *pdlyb_cfg)
3410 {
3411   HAL_StatusTypeDef status = HAL_ERROR;
3412 
3413   if (hospi->Instance == OCTOSPI1)
3414   {
3415     LL_DLYB_GetDelay(DLYB_OCTOSPI1, pdlyb_cfg);
3416     status = HAL_OK;
3417   }
3418 #if defined (OCTOSPI2)
3419   else if (hospi->Instance == OCTOSPI2)
3420   {
3421     LL_DLYB_GetDelay(DLYB_OCTOSPI2, pdlyb_cfg);
3422     status = HAL_OK;
3423   }
3424 #endif /* OCTOSPI2 */
3425 
3426   else
3427   {
3428     /* Nothing to do */
3429   }
3430 
3431   /* Return function status */
3432   return status;
3433 }
3434 
3435 /**
3436   * @brief  Get the Delay line length value.
3437   * @param  hospi   : OSPI handle.
3438   * @retval HAL status.
3439   */
HAL_OSPI_DLYB_GetClockPeriod(OSPI_HandleTypeDef * hospi,HAL_OSPI_DLYB_CfgTypeDef * pdlyb_cfg)3440 HAL_StatusTypeDef HAL_OSPI_DLYB_GetClockPeriod(OSPI_HandleTypeDef *hospi, HAL_OSPI_DLYB_CfgTypeDef  *pdlyb_cfg)
3441 {
3442   HAL_StatusTypeDef status = HAL_ERROR;
3443 
3444   /* Enable OCTOSPI Free Running Clock (mandatory) */
3445   SET_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
3446 
3447   /* Update OCTOSPI state */
3448   hospi->State = HAL_OSPI_STATE_BUSY_CMD;
3449 
3450   if (hospi->Instance == OCTOSPI1)
3451   {
3452     /* Enable the DelayBlock */
3453     LL_DLYB_Enable(DLYB_OCTOSPI1);
3454 
3455     /* try to detect Period */
3456     if (LL_DLYB_GetClockPeriod(DLYB_OCTOSPI1, pdlyb_cfg) == (uint32_t)SUCCESS)
3457     {
3458       status = HAL_OK;
3459     }
3460 
3461     /* Disable the DelayBlock */
3462     LL_DLYB_Disable(DLYB_OCTOSPI1);
3463   }
3464 
3465 #if defined (OCTOSPI2)
3466   else if (hospi->Instance == OCTOSPI2)
3467   {
3468     /* Enable the DelayBlock */
3469     LL_DLYB_Enable(DLYB_OCTOSPI2);
3470 
3471     /* try to detect Period */
3472     if (LL_DLYB_GetClockPeriod(DLYB_OCTOSPI2, pdlyb_cfg) == (uint32_t)SUCCESS)
3473     {
3474       status = HAL_OK;
3475     }
3476 
3477     /* Disable the DelayBlock */
3478     LL_DLYB_Disable(DLYB_OCTOSPI2);
3479   }
3480 #endif /* OCTOSPI2 */
3481 
3482   else
3483   {
3484     /* Nothing to do */
3485   }
3486 
3487   /* Abort the current OctoSPI operation if exist */
3488   (void)HAL_OSPI_Abort(hospi);
3489 
3490   /* Disable Free Running Clock */
3491   CLEAR_BIT(hospi->Instance->DCR1, OCTOSPI_DCR1_FRCK);
3492 
3493   /* Return function status */
3494   return status;
3495 }
3496 /**
3497   @endcond
3498   */
3499 
3500 /**
3501   * @}
3502   */
3503 
3504 #endif /* HAL_OSPI_MODULE_ENABLED */
3505 
3506 /**
3507   * @}
3508   */
3509 
3510 /**
3511   * @}
3512   */
3513 
3514 #endif /* OCTOSPI || OCTOSPI1 || OCTOSPI2 */
3515