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