1 /*
2 * Copyright 2021-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @file Qspi_Ip.c
9 *
10 * @addtogroup IPV_QSPI
11 * @{
12 */
13
14
15 #ifdef __cplusplus
16 extern "C"{
17 #endif
18
19 #include "Mcal.h"
20 #include "OsIf.h"
21 #include "Qspi_Ip_Controller.h"
22 #include "Qspi_Ip_Common.h"
23 #include "Qspi_Ip.h"
24 #include "Qspi_Ip_Hyperflash.h"
25
26
27 /*==================================================================================================
28 * SOURCE FILE VERSION INFORMATION
29 ==================================================================================================*/
30 #define QSPI_IP_VENDOR_ID_C 43
31 #define QSPI_IP_AR_RELEASE_MAJOR_VERSION_C 4
32 #define QSPI_IP_AR_RELEASE_MINOR_VERSION_C 7
33 #define QSPI_IP_AR_RELEASE_REVISION_VERSION_C 0
34 #define QSPI_IP_SW_MAJOR_VERSION_C 2
35 #define QSPI_IP_SW_MINOR_VERSION_C 0
36 #define QSPI_IP_SW_PATCH_VERSION_C 0
37 /*==================================================================================================
38 * FILE VERSION CHECKS
39 ==================================================================================================*/
40 #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
41 /* Check if current file and Mcal.h header file are of the same Autosar version */
42 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != MCAL_AR_RELEASE_MAJOR_VERSION) || \
43 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != MCAL_AR_RELEASE_MINOR_VERSION) \
44 )
45 #error "AutoSar Version Numbers of Qspi_Ip.c and Mcal.h are different"
46 #endif
47
48 /* Check if current file and OsIf.h header file are of the same Autosar version */
49 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != OSIF_AR_RELEASE_MAJOR_VERSION) || \
50 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != OSIF_AR_RELEASE_MINOR_VERSION) \
51 )
52 #error "AutoSar Version Numbers of Qspi_Ip.c and OsIf.h are different"
53 #endif
54 #endif
55
56 /* Check if current file and Qspi_Ip_Controller header file are of the same vendor */
57 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_CONTROLLER_VENDOR_ID_H)
58 #error "Qspi_Ip.c and Qspi_Ip_Controller.h have different vendor ids"
59 #endif
60 /* Check if current file and Qspi_Ip_Controller header file are of the same Autosar version */
61 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != QSPI_IP_CONTROLLER_AR_RELEASE_MAJOR_VERSION_H) || \
62 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != QSPI_IP_CONTROLLER_AR_RELEASE_MINOR_VERSION_H) || \
63 (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_CONTROLLER_AR_RELEASE_REVISION_VERSION_H) \
64 )
65 #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Controller.h are different"
66 #endif
67 /* Check if current file and Qspi_Ip_Controller header file are of the same Software version */
68 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_CONTROLLER_SW_MAJOR_VERSION_H) || \
69 (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_CONTROLLER_SW_MINOR_VERSION_H) || \
70 (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_CONTROLLER_SW_PATCH_VERSION_H) \
71 )
72 #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Controller.h are different"
73 #endif
74
75 /* Check if current file and Qspi_Ip_Common header file are of the same vendor */
76 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_COMMON_VENDOR_ID_H)
77 #error "Qspi_Ip.c and Qspi_Ip_Common.h have different vendor ids"
78 #endif
79 /* Check if current file and Qspi_Ip_Common header file are of the same Autosar version */
80 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != QSPI_IP_COMMON_AR_RELEASE_MAJOR_VERSION_H) || \
81 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != QSPI_IP_COMMON_AR_RELEASE_MINOR_VERSION_H) || \
82 (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_COMMON_AR_RELEASE_REVISION_VERSION_H) \
83 )
84 #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Common.h are different"
85 #endif
86 /* Check if current file and Qspi_Ip_Common header file are of the same Software version */
87 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_COMMON_SW_MAJOR_VERSION_H) || \
88 (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_COMMON_SW_MINOR_VERSION_H) || \
89 (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_COMMON_SW_PATCH_VERSION_H) \
90 )
91 #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Common.h are different"
92 #endif
93
94 /* Check if current file and Qspi_Ip header file are of the same vendor */
95 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_VENDOR_ID_H)
96 #error "Qspi_Ip.c and Qspi_Ip.h have different vendor ids"
97 #endif
98 /* Check if current file and Qspi_Ip header file are of the same Autosar version */
99 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != QSPI_IP_AR_RELEASE_MAJOR_VERSION_H) || \
100 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != QSPI_IP_AR_RELEASE_MINOR_VERSION_H) || \
101 (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_AR_RELEASE_REVISION_VERSION_H) \
102 )
103 #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip.h are different"
104 #endif
105 /* Check if current file and Qspi_Ip header file are of the same Software version */
106 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_SW_MAJOR_VERSION_H) || \
107 (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_SW_MINOR_VERSION_H) || \
108 (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_SW_PATCH_VERSION_H) \
109 )
110 #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip.h are different"
111 #endif
112
113 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same vendor */
114 #if (QSPI_IP_VENDOR_ID_C != QSPI_IP_HYPERFLASH_VENDOR_ID_H)
115 #error "Qspi_Ip.c and Qspi_Ip_Hyperflash.h have different vendor ids"
116 #endif
117 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same Autosar version */
118 #if ((QSPI_IP_AR_RELEASE_MAJOR_VERSION_C != QSPI_IP_HYPERFLASH_AR_RELEASE_MAJOR_VERSION_H) || \
119 (QSPI_IP_AR_RELEASE_MINOR_VERSION_C != QSPI_IP_HYPERFLASH_AR_RELEASE_MINOR_VERSION_H) || \
120 (QSPI_IP_AR_RELEASE_REVISION_VERSION_C != QSPI_IP_HYPERFLASH_AR_RELEASE_REVISION_VERSION_H) \
121 )
122 #error "AutoSar Version Numbers of Qspi_Ip.c and Qspi_Ip_Hyperflash.h are different"
123 #endif
124 /* Check if current file and Qspi_Ip_Hyperflash header file are of the same Software version */
125 #if ((QSPI_IP_SW_MAJOR_VERSION_C != QSPI_IP_HYPERFLASH_SW_MAJOR_VERSION_H) || \
126 (QSPI_IP_SW_MINOR_VERSION_C != QSPI_IP_HYPERFLASH_SW_MINOR_VERSION_H) || \
127 (QSPI_IP_SW_PATCH_VERSION_C != QSPI_IP_HYPERFLASH_SW_PATCH_VERSION_H) \
128 )
129 #error "Software Version Numbers of Qspi_Ip.c and Qspi_Ip_Hyperflash.h are different"
130 #endif
131
132
133 /*******************************************************************************
134 * Variables
135 ******************************************************************************/
136 #if (QSPI_IP_MEM_INSTANCE_COUNT > 0)
137
138 /*When multicore type3 is enabled on MemAcc, global variables must be allocated to share memory section */
139 #if( QSPI_IP_MULTICORE_ENABLED == STD_ON)
140 #define MEM_43_EXFLS_START_SEC_VAR_SHARED_CLEARED_UNSPECIFIED_NO_CACHEABLE
141 #else
142 #define MEM_43_EXFLS_START_SEC_VAR_CLEARED_UNSPECIFIED
143 #endif
144 #include "Mem_43_EXFLS_MemMap.h"
145
146 /* Pointer to runtime state structures */
147 VAR_SEC_NOCACHE(Qspi_Ip_MemoryStateStructure) Qspi_Ip_StateType Qspi_Ip_MemoryStateStructure[QSPI_IP_MEM_INSTANCE_COUNT];
148
149 #if( QSPI_IP_MULTICORE_ENABLED == STD_ON)
150 #define MEM_43_EXFLS_STOP_SEC_VAR_SHARED_CLEARED_UNSPECIFIED_NO_CACHEABLE
151 #else
152 #define MEM_43_EXFLS_STOP_SEC_VAR_CLEARED_UNSPECIFIED
153 #endif
154 #include "Mem_43_EXFLS_MemMap.h"
155
156 /*******************************************************************************
157 * Macros
158 ******************************************************************************/
159
160
161 /*******************************************************************************
162 * Private Functions
163 ******************************************************************************/
164
165 #define MEM_43_EXFLS_START_SEC_CODE
166 #include "Mem_43_EXFLS_MemMap.h"
167
168 static Qspi_Ip_StatusType Qspi_Ip_WriteEnable(uint32 instance);
169
170 static Qspi_Ip_StatusType Qspi_Ip_InitReset(uint32 instance,
171 uint16 resetCmdLut,
172 uint8 resetCmdCount,
173 const Qspi_Ip_StateType *state
174 );
175
176 static Qspi_Ip_StatusType Qspi_Ip_InitWriteReg(uint32 instance,
177 const Qspi_Ip_InitOperationType *operation
178 );
179
180 static Qspi_Ip_StatusType Qspi_Ip_InitRMWReg(uint32 instance,
181 const Qspi_Ip_InitOperationType *operation
182 );
183
184 static Qspi_Ip_StatusType Qspi_Ip_InitReadReg(uint32 instance,
185 const Qspi_Ip_InitOperationType *operation
186 );
187
188 static Qspi_Ip_StatusType Qspi_Ip_InitProtection(uint32 instance,
189 const Qspi_Ip_StateType *state
190 );
191
192 static Qspi_Ip_StatusType Qspi_Ip_InitOperation(uint32 instance,
193 const Qspi_Ip_StateType *state,
194 uint8 initOp
195 );
196
197 static inline uint32 Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType *state,
198 uint32 *address,
199 uint32 *size
200 );
201
202 static uint16 Qspi_Ip_InitLutSeq(uint32 instance,
203 uint16 VirtualLut,
204 uint8 LutRegister
205 );
206
207 static void Qspi_Ip_DeinitLutSeq(uint32 instance,
208 uint8 LutRegister
209 );
210
211 /*FUNCTION**********************************************************************
212 *
213 * Function Name : Qspi_Ip_InitLutSeq
214 * Description : Initializes one sequence in the LUT table from a virtual table sequence. Returns start index of next sequence.
215 */
Qspi_Ip_InitLutSeq(uint32 instance,uint16 VirtualLut,uint8 LutRegister)216 static uint16 Qspi_Ip_InitLutSeq(uint32 instance,
217 uint16 VirtualLut,
218 uint8 LutRegister
219 )
220 {
221 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
222 const Qspi_Ip_InstrOpType *virtualLutTable = state->configuration->lutSequences.lutOps;
223 Qspi_Ip_InstrOpType operation1, operation2;
224 uint16 vLutIdx = VirtualLut; /* Index in virtual LUT */
225 uint8 pLutIdx = 0U; /* Index in physical LUT */
226 uint32 lutData[FEATURE_QSPI_LUT_SEQUENCE_SIZE]; /* Data to be written to the physical LUTs */
227
228 do
229 {
230 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
231 DEV_ASSERT_QSPI(vLutIdx < state->configuration->lutSequences.opCount);
232 #endif
233 operation1 = virtualLutTable[vLutIdx];
234 vLutIdx++;
235 operation2 = QSPI_IP_LUT_SEQ_END;
236 if (operation1 != QSPI_IP_LUT_SEQ_END)
237 {
238 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
239 DEV_ASSERT_QSPI(vLutIdx < state->configuration->lutSequences.opCount);
240 #endif
241 operation2 = virtualLutTable[vLutIdx];
242 vLutIdx++;
243 }
244 /* Add two operations to lut sequence */
245 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
246 DEV_ASSERT_QSPI(pLutIdx < FEATURE_QSPI_LUT_SEQUENCE_SIZE);
247 #endif
248 lutData[pLutIdx] = QSPI_IP_PACK_LUT_REG(operation1, operation2);
249 pLutIdx++;
250 }
251 while (operation2 != QSPI_IP_LUT_SEQ_END);
252
253 #if (FEATURE_QSPI_HAS_SFP == 1)
254 /* Clear the rest of sequence to avoid the effect of the previous command.
255 This prevent the SFP block from identifying the wrong type of transaction.
256 */
257 for (; pLutIdx < FEATURE_QSPI_LUT_SEQUENCE_SIZE; pLutIdx++)
258 {
259 lutData[pLutIdx] = QSPI_IP_PACK_LUT_REG(QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END);
260 }
261 #endif
262
263 /* Write data to physical LUT registers */
264 Qspi_Ip_WriteLuts(state->connection->qspiInstance, FEATURE_QSPI_LUT_SEQUENCE_SIZE * LutRegister, lutData, pLutIdx);
265
266 return vLutIdx;
267 }
268
269
270 /*FUNCTION**********************************************************************
271 *
272 * Function Name : Qspi_Ip_DeinitLutSeq
273 * Description : DeInitializes one sequence in the LUT table from a virtual table sequence.
274 */
Qspi_Ip_DeinitLutSeq(uint32 instance,uint8 LutRegister)275 static void Qspi_Ip_DeinitLutSeq(uint32 instance,
276 uint8 LutRegister
277 )
278 {
279 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
280 const uint32 lutData[FEATURE_QSPI_LUT_SEQUENCE_SIZE] = {0U}; /* Data to be written to the physical LUTs */
281
282 /* Write data to physical LUT registers */
283 Qspi_Ip_WriteLuts(state->connection->qspiInstance, FEATURE_QSPI_LUT_SEQUENCE_SIZE * LutRegister, lutData, FEATURE_QSPI_LUT_SEQUENCE_SIZE);
284 }
285
286
287 /*FUNCTION**********************************************************************
288 *
289 * Function Name : Qspi_Ip_SetValue
290 * Description : Converts a long value in data to be sent to flash
291 */
Qspi_Ip_SetValue(uint8 * data,uint8 size,uint32 value)292 static inline void Qspi_Ip_SetValue(uint8 *data,
293 uint8 size,
294 uint32 value
295 )
296 {
297 uint8 cnt;
298 uint32 temp = value;
299
300 /* Put value in the data buffer */
301 for (cnt = 0U; cnt < size; cnt++)
302 {
303 data[cnt] = (uint8)(temp & 0xFFU);
304 temp >>= 8U;
305 }
306 }
307
308 /*FUNCTION**********************************************************************
309 *
310 * Function Name : Qspi_Ip_SetBitfield
311 * Description : Sets a new value in a register bitfield
312 */
Qspi_Ip_SetBitfield(uint8 * data,uint8 size,uint8 shift,uint8 width,uint32 value)313 static void Qspi_Ip_SetBitfield(uint8 *data,
314 uint8 size,
315 uint8 shift,
316 uint8 width,
317 uint32 value
318 )
319 {
320 uint8 cnt;
321 uint32 longData = 0UL;
322 uint32 mask;
323
324 /* Pack data in a long value (data[0] is LSB, data[size-1] is MSB) */
325 for (cnt = 0U; cnt < size; cnt++)
326 {
327 longData = (longData << 8U) + data[size - 1U - cnt];
328 }
329 /* Apply change */
330 mask = ((1UL << (uint32)width) - 1UL) << (uint32)shift;
331 longData &= ~mask;
332 longData |= (value << shift) & mask;
333 /* Put data back in the data buffer (data[0] is LSB, data[size-1] is MSB) */
334 for (cnt = 0U; cnt < size; cnt++)
335 {
336 data[cnt] = (uint8)(longData & 0xFFU);
337 longData >>= 8U;
338 }
339 }
340
341
342 /*FUNCTION**********************************************************************
343 *
344 * Function Name : Qspi_Ip_GetBitfield
345 * Description : Extracts the value of a register bitfield
346 */
Qspi_Ip_GetBitfield(const uint8 * data,uint8 size,uint8 shift,uint8 width)347 static uint32 Qspi_Ip_GetBitfield(const uint8 *data,
348 uint8 size,
349 uint8 shift,
350 uint8 width
351 )
352 {
353 uint8 cnt;
354 uint32 longData = 0U;
355 uint32 mask;
356 uint32 value;
357
358 /* Pack data in a long value (data[0] is LSB, data[size-1] is MSB) */
359 for (cnt = 0U; cnt < size; cnt++)
360 {
361 longData = (longData << 8U) + data[size - 1U - cnt];
362 }
363 /* Extract field */
364 mask = (1UL << (uint32)width) - 1UL;
365 value = (longData >> shift) & mask;
366 return value;
367 }
368
369
370 /*FUNCTION**********************************************************************
371 *
372 * Function Name : Qspi_Ip_UpdateStatusReg
373 * Description : Updates a bitfield in the status register
374 * @implements Qspi_Ip_UpdateStatusReg_Activity */
Qspi_Ip_UpdateStatusReg(uint32 instance,uint8 offset,uint8 width,uint8 value)375 static Qspi_Ip_StatusType Qspi_Ip_UpdateStatusReg(uint32 instance,
376 uint8 offset,
377 uint8 width,
378 uint8 value
379 )
380 {
381 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
382 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
383 uint8 data[4U];
384 Qspi_Ip_StatusType status;
385
386 /* Read status register */
387 status = Qspi_Ip_RunReadCommand(instance, statusConfig->statusRegReadLut, 0U, data, NULL_PTR, statusConfig->regSize);
388
389 if (STATUS_QSPI_IP_SUCCESS == status)
390 {
391 /* Check existing value, write status register only if needed */
392 if (value != Qspi_Ip_GetBitfield(data, statusConfig->regSize, offset, width))
393 {
394 Qspi_Ip_SetBitfield(data, statusConfig->regSize, offset, width, value);
395 }
396 /* send WREN command for status register */
397 if (statusConfig->writeEnableSRLut != QSPI_IP_LUT_INVALID)
398 {
399 status = Qspi_Ip_RunCommand(instance, statusConfig->writeEnableSRLut, 0U);
400 }
401 if (STATUS_QSPI_IP_SUCCESS == status)
402 {
403 /* send write status register command */
404 status = Qspi_Ip_RunWriteCommand(instance, statusConfig->statusRegWriteLut, 0U, data, statusConfig->regSize);
405 }
406 }
407
408 return status;
409 }
410
411 /*FUNCTION**********************************************************************
412 *
413 * Function Name : Qspi_Ip_CheckStatusReg
414 * Description : Checks a bitfield in the status register
415 * @implements Qspi_Ip_CheckStatusReg_Activity */
Qspi_Ip_CheckStatusReg(uint32 instance,uint8 offset,uint8 width,uint8 * value)416 static Qspi_Ip_StatusType Qspi_Ip_CheckStatusReg(uint32 instance,
417 uint8 offset,
418 uint8 width,
419 uint8 *value
420 )
421 {
422 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
423 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
424 uint8 data[4];
425 Qspi_Ip_StatusType status;
426
427 /* Read status register */
428 status = Qspi_Ip_RunReadCommand(instance, statusConfig->statusRegReadLut, 0U, data, NULL_PTR, statusConfig->regSize);
429 if (STATUS_QSPI_IP_SUCCESS == status)
430 {
431 /* Extract bit-field */
432 *value = (uint8)Qspi_Ip_GetBitfield(data, statusConfig->regSize, offset, width);
433 }
434
435 return status;
436 }
437
438
439 /*FUNCTION**********************************************************************
440 *
441 * Function Name : Qspi_Ip_WriteEnable
442 * Description : Enables the serial flash memory for a program or erase operation
443 * @implements Qspi_Ip_WriteEnable_Activity */
Qspi_Ip_WriteEnable(uint32 instance)444 static Qspi_Ip_StatusType Qspi_Ip_WriteEnable(uint32 instance)
445 {
446 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
447 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
448
449 uint32 retries = QSPI_IP_MAX_RETRY + 1U;
450 Qspi_Ip_StatusType status = STATUS_QSPI_IP_TIMEOUT;
451 Qspi_Ip_StatusType cmdStatus;
452 uint8 welValue = 0U;
453
454 MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_WAIT_IN_WREN);
455
456 while (retries > 0UL)
457 {
458 /* send WREN command */
459 cmdStatus = Qspi_Ip_RunCommand(instance, statusConfig->writeEnableLut, 0U);
460 if (cmdStatus != STATUS_QSPI_IP_SUCCESS)
461 {
462 status = cmdStatus;
463 }
464 /* check WEL bit */
465 cmdStatus = Qspi_Ip_CheckStatusReg(instance, statusConfig->writeEnableOffset, 1U, &welValue);
466 if (STATUS_QSPI_IP_SUCCESS == cmdStatus)
467 {
468 /* 1 == check WEL */
469 if (1U == welValue)
470 {
471 status = STATUS_QSPI_IP_SUCCESS;
472 break;
473 }
474 }
475 else
476 {
477 /* record error */
478 status = cmdStatus;
479 }
480 retries--;
481 }
482
483 return status;
484 }
485
486
487 /*FUNCTION**********************************************************************
488 *
489 * Function Name : Qspi_Ip_SerialflashSectorErase
490 * Description : Erase a sector in the serial flash.
491 */
Qspi_Ip_SerialflashSectorErase(uint32 instance,uint32 address,uint16 eraseLut)492 static Qspi_Ip_StatusType Qspi_Ip_SerialflashSectorErase(uint32 instance,
493 uint32 address,
494 uint16 eraseLut
495 )
496 {
497 Qspi_Ip_StatusType status;
498
499 /* enable write before erasing */
500 status = Qspi_Ip_WriteEnable(instance);
501
502 MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_WAIT_IN_BASICERS);
503
504 if (STATUS_QSPI_IP_SUCCESS == status)
505 {
506 /* launch erase command and return */
507 status = Qspi_Ip_RunCommand(instance, eraseLut, address);
508 }
509
510 return status;
511 }
512
513
514 /*FUNCTION**********************************************************************
515 *
516 * Function Name : Qspi_Ip_BasicErase
517 * Description : Perform one of the supported erase types in the serial flash.
518 * @implements Qspi_Ip_BasicErase_Activity */
Qspi_Ip_BasicErase(uint32 instance,uint32 address,uint16 eraseLut)519 static Qspi_Ip_StatusType Qspi_Ip_BasicErase(uint32 instance,
520 uint32 address,
521 uint16 eraseLut
522 )
523 {
524 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
525 Qspi_Ip_StatusType status;
526
527 /* Check device type */
528 switch (state->configuration->memType)
529 {
530 case QSPI_IP_HYPER_FLASH:
531 status = Qspi_Ip_HyperflashSectorErase(instance, address);
532 break;
533
534 case QSPI_IP_SERIAL_FLASH:
535 status = Qspi_Ip_SerialflashSectorErase(instance, address, eraseLut);
536 break;
537 default:
538 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
539 break;
540 }
541
542 return status;
543 }
544
545
546 /*FUNCTION**********************************************************************
547 *
548 * Function Name : Qspi_Ip_CheckMemoryStatus
549 * Description : Check that the memory is idle. Used internally by the driver during initialization
550 */
Qspi_Ip_CheckMemoryStatus(uint32 instance,uint16 virtualLut)551 static Qspi_Ip_StatusType Qspi_Ip_CheckMemoryStatus(uint32 instance,
552 uint16 virtualLut
553 )
554 {
555 Qspi_Ip_StatusType status;
556 uint8 busyValue;
557 uint8 data[4];
558 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
559 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
560
561 /* Check if the QuadSPI controller is idle */
562 status = Qspi_Ip_ControllerGetStatus(state->connection->qspiInstance);
563 if (STATUS_QSPI_IP_SUCCESS == status)
564 {
565 /* Check if the operation has finished in the serial flash */
566 /* Read status register */
567 status = Qspi_Ip_RunReadCommand(instance, virtualLut, 0U, data, NULL_PTR, statusConfig->regSize);
568 if (STATUS_QSPI_IP_SUCCESS == status)
569 {
570 /* Extract bit-field */
571 busyValue = (uint8)Qspi_Ip_GetBitfield(data, statusConfig->regSize, statusConfig->busyOffset, 1U);
572 if (busyValue == statusConfig->busyValue)
573 {
574 /* Flash device is busy */
575 status = STATUS_QSPI_IP_BUSY;
576 }
577 MCAL_FAULT_INJECTION_POINT(FLS_FIP_SR_BUSY_CHECKCOMMANDCOMPLETE);
578 }
579 }
580
581 return status;
582 }
583
584
585 /*FUNCTION**********************************************************************
586 *
587 * Function Name : Qspi_Ip_WaitCommandComplete
588 * Description : Wait until external memory is not busy
589 */
Qspi_Ip_WaitCommandComplete(uint32 instance,uint16 VirtualLut)590 static Qspi_Ip_StatusType Qspi_Ip_WaitCommandComplete(uint32 instance,
591 uint16 VirtualLut
592 )
593 {
594 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
595 uint32 ElapsedTicks = 0UL;
596 uint32 TimeoutTicks;
597 uint32 CurrentTicks;
598
599 /* Prepare timeout counter */
600 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_FLS_INIT_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
601 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
602 /* Wait for the command to complete */
603 do
604 {
605 /* Get memory status */
606 status = Qspi_Ip_CheckMemoryStatus(instance, VirtualLut);
607 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
608 /* Check timeout */
609 if (ElapsedTicks >= TimeoutTicks)
610 {
611 status = STATUS_QSPI_IP_TIMEOUT;
612 break;
613 }
614 }
615 while (STATUS_QSPI_IP_BUSY == status);
616
617 return status;
618 }
619
620
621 /*FUNCTION**********************************************************************
622 *
623 * Function Name : Qspi_Ip_WaitResetComplete
624 * Description : Wait until external memory is available for operation after a reset
625 * @implements Qspi_Ip_CheckResetComplete_Activity */
Qspi_Ip_WaitResetComplete(void)626 static void Qspi_Ip_WaitResetComplete(void)
627 {
628 uint32 ElapsedTicks = 0UL;
629 uint32 TimeoutTicks;
630 uint32 CurrentTicks;
631
632 /* Prepare timeout counter */
633 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_RESET_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
634 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
635 /* Wait for the specified time */
636 do
637 {
638 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
639 }
640 while (ElapsedTicks < TimeoutTicks);
641 }
642
643
644 /*FUNCTION**********************************************************************
645 *
646 * Function Name : Qspi_Ip_InitWriteReg
647 * Description : Write the configured value into a register of external flash device
648 * @implements Qspi_Ip_InitWriteReg_Activity */
Qspi_Ip_InitWriteReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)649 static Qspi_Ip_StatusType Qspi_Ip_InitWriteReg(uint32 instance,
650 const Qspi_Ip_InitOperationType * operation
651 )
652 {
653 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
654 uint8 value[4U];
655
656 /* write a value in a register */
657 if (QSPI_IP_LUT_INVALID != operation->weLut)
658 {
659 /* send WREN command */
660 status = Qspi_Ip_RunCommand(instance, operation->weLut, operation->addr);
661 }
662 if (STATUS_QSPI_IP_SUCCESS == status)
663 {
664 Qspi_Ip_SetValue(value, operation->size, operation->value);
665 status = Qspi_Ip_RunWriteCommand(instance, operation->command1Lut, operation->addr, value, operation->size);
666 }
667
668 return status;
669 }
670
671
672 /*FUNCTION**********************************************************************
673 *
674 * Function Name : Qspi_Ip_InitRMWReg
675 * Description : Change a bitfield in a register of external flash device
676 * @implements Qspi_Ip_InitRMWReg_Activity */
Qspi_Ip_InitRMWReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)677 static Qspi_Ip_StatusType Qspi_Ip_InitRMWReg(uint32 instance,
678 const Qspi_Ip_InitOperationType *operation
679 )
680 {
681 Qspi_Ip_StatusType status;
682 uint32 fieldVal;
683 uint8 value[4U];
684
685 /* Read current register value */
686 status = Qspi_Ip_RunReadCommand(instance, operation->command1Lut, operation->addr, value, NULL_PTR, operation->size);
687 if (STATUS_QSPI_IP_SUCCESS == status)
688 {
689 /* Retrieve target bitfield */
690 fieldVal = Qspi_Ip_GetBitfield(value, operation->size, operation->shift, operation->width);
691 if (fieldVal != operation->value)
692 {
693 /* Modify target bitfield */
694 Qspi_Ip_SetBitfield(value, operation->size, operation->shift, operation->width, operation->value);
695 if (QSPI_IP_LUT_INVALID != operation->weLut)
696 {
697 /* Send WREN command */
698 status = Qspi_Ip_RunCommand(instance, operation->weLut, operation->addr);
699 }
700 if (STATUS_QSPI_IP_SUCCESS == status)
701 {
702 /* Write back register value; use second LUT command */
703 status = Qspi_Ip_RunWriteCommand(instance, operation->command2Lut, operation->addr, (uint8 *)&value, operation->size);
704 }
705 }
706 }
707
708 return status;
709 }
710
711
712 /*FUNCTION**********************************************************************
713 *
714 * Function Name : Qspi_Ip_InitReadReg
715 * Description : Read the register's value of external flash device and loop until matching the configured one
716 * @implements Qspi_Ip_InitReadReg_Activity */
Qspi_Ip_InitReadReg(uint32 instance,const Qspi_Ip_InitOperationType * operation)717 static Qspi_Ip_StatusType Qspi_Ip_InitReadReg(uint32 instance,
718 const Qspi_Ip_InitOperationType *operation
719 )
720 {
721 Qspi_Ip_StatusType status;
722 uint32 fieldVal = 0xFFFFFFFFUL; /* Invalid initial value */
723 uint8 value[4U];
724 uint32 ElapsedTicks = 0UL;
725 uint32 TimeoutTicks;
726 uint32 CurrentTicks;
727
728 /* Prepare timeout counter */
729 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_FLS_INIT_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
730 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
731 do
732 {
733 /* read current register value */
734 status = Qspi_Ip_RunReadCommand(instance, operation->command1Lut, operation->addr, value, NULL_PTR, operation->size);
735 if (STATUS_QSPI_IP_SUCCESS == status)
736 {
737 /* retrieve target bitfield */
738 fieldVal = Qspi_Ip_GetBitfield(value, operation->size, operation->shift, operation->width);
739 }
740 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
741 if (ElapsedTicks >= TimeoutTicks)
742 {
743 status = STATUS_QSPI_IP_TIMEOUT;
744 break;
745 }
746 }
747 while (fieldVal != operation->value);
748
749 return status;
750 }
751
752 /*FUNCTION**********************************************************************
753 *
754 * Function Name : Qspi_Ip_InitOperation
755 * Description : Execute initialization sequence to get the serial flash memory in the target state for operation */
Qspi_Ip_InitOperation(uint32 instance,const Qspi_Ip_StateType * state,uint8 initOp)756 static Qspi_Ip_StatusType Qspi_Ip_InitOperation(uint32 instance,
757 const Qspi_Ip_StateType *state,
758 uint8 initOp
759 )
760 {
761 const Qspi_Ip_InitOperationType *initOperations = state->configuration->initConfiguration.operations;
762 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
763
764 switch (initOperations[initOp].opType)
765 {
766 case QSPI_IP_OP_TYPE_CMD:
767 /* Execute a simple command */
768 status = Qspi_Ip_RunCommand(instance, initOperations[initOp].command1Lut, initOperations[initOp].addr);
769 break;
770
771 case QSPI_IP_OP_TYPE_WRITE_REG:
772 /* Write value into the register */
773 status = Qspi_Ip_InitWriteReg(instance, &initOperations[initOp]);
774 break;
775
776 case QSPI_IP_OP_TYPE_RMW_REG:
777 /* Change a bitfield in the register */
778 status = Qspi_Ip_InitRMWReg(instance, &initOperations[initOp]);
779 break;
780
781 case QSPI_IP_OP_TYPE_READ_REG:
782 /* Check a bitfield in the register */
783 status = Qspi_Ip_InitReadReg(instance, &initOperations[initOp]);
784 break;
785
786 case QSPI_IP_OP_TYPE_QSPI_CFG:
787 /* Re-initialize QSPI controller with the given configuration */
788 (void)Qspi_Ip_ControllerDeinit(state->connection->qspiInstance);
789 status = Qspi_Ip_ControllerInit(state->connection->qspiInstance, initOperations[initOp].ctrlCfgPtr);
790 break;
791
792 default:
793 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
794 break;
795 } /* switch */
796
797 return status;
798
799 }
800
801 /*FUNCTION**********************************************************************
802 *
803 * Function Name : Qspi_Ip_InitDevice
804 * Description : Execute initialization sequence to get the serial flash memory in the target state for operation
805 * @implements Qspi_Ip_InitDevice_Activity */
Qspi_Ip_InitDevice(uint32 instance,const Qspi_Ip_StateType * state)806 static Qspi_Ip_StatusType Qspi_Ip_InitDevice(uint32 instance,
807 const Qspi_Ip_StateType *state
808 )
809 {
810 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
811 uint8 initConfigOpCount = state->configuration->initConfiguration.opCount;
812 uint8 initOp;
813
814 MCAL_FAULT_INJECTION_POINT(FLS_FIP_FR_ERROR_IPCOMMAND_INITDEVICE);
815
816 /* Perform operations in initialization list (common) */
817 for (initOp = 0; initOp < initConfigOpCount; initOp++)
818 {
819 status = Qspi_Ip_InitOperation(instance, state, initOp);
820
821 if (STATUS_QSPI_IP_SUCCESS != status)
822 {
823 break;
824 }
825 }
826
827 /* Perform device initialization (specific) */
828 if (STATUS_QSPI_IP_SUCCESS == status)
829 {
830
831 if (QSPI_IP_HYPER_FLASH == state->configuration->memType)
832 {
833 status = Qspi_Ip_HyperflashInit(instance);
834 }
835 }
836 else
837 {
838 status = STATUS_QSPI_IP_ERROR;
839 }
840
841 return status;
842 }
843
844
845 /*FUNCTION**********************************************************************
846 *
847 * Function Name : Qspi_Ip_InitProtection
848 * Description : Update the protection configuration value if needed
849 * @implements Qspi_Ip_InitProtection_Activity */
Qspi_Ip_InitProtection(uint32 instance,const Qspi_Ip_StateType * state)850 static Qspi_Ip_StatusType Qspi_Ip_InitProtection(uint32 instance,
851 const Qspi_Ip_StateType *state
852 )
853 {
854 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
855 uint8 configProtection = state->configuration->statusConfig.blockProtectionValue;
856 uint8 getProtection = 0U;
857
858 if (state->configuration->statusConfig.blockProtectionWidth != 0U)
859 {
860 /* Ensure the previous command is completed */
861 status = Qspi_Ip_WaitCommandComplete(instance, state->configuration->statusConfig.statusRegReadLut);
862 if (STATUS_QSPI_IP_SUCCESS == status)
863 {
864 /* Read and check the current setting */
865 status = Qspi_Ip_GetProtection(instance, &getProtection);
866 if ((STATUS_QSPI_IP_SUCCESS == status) && (getProtection != configProtection))
867 {
868 /* Set new setting */
869 status = Qspi_Ip_SetProtection(instance, configProtection);
870 if (STATUS_QSPI_IP_SUCCESS == status)
871 {
872 /* Ensure the write is completed */
873 status = Qspi_Ip_WaitCommandComplete(instance, state->configuration->statusConfig.statusRegReadLut);
874 }
875 }
876 }
877 }
878
879 return status;
880 }
881
882
883 /*FUNCTION**********************************************************************
884 *
885 * Function Name : Qspi_Ip_InitReset
886 * Description : Perform the software reset sequence
887 * @implements Qspi_Ip_InitReset_Activity */
Qspi_Ip_InitReset(uint32 instance,uint16 resetCmdLut,uint8 resetCmdCount,const Qspi_Ip_StateType * state)888 static Qspi_Ip_StatusType Qspi_Ip_InitReset(uint32 instance,
889 uint16 resetCmdLut,
890 uint8 resetCmdCount,
891 const Qspi_Ip_StateType *state
892 )
893 {
894 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
895 uint16 virtualLut = resetCmdLut;
896 uint8 cnt;
897
898 if (QSPI_IP_LUT_INVALID != resetCmdLut)
899 {
900 for (cnt = 0U; cnt < resetCmdCount; cnt++)
901 {
902 /* Copy sequence in LUT registers */
903 virtualLut = Qspi_Ip_InitLutSeq(instance, virtualLut, QSPI_IP_COMMAND_LUT);
904
905 /* Run QSPI command */
906 status = Qspi_Ip_IpCommand(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress);
907 if (status != STATUS_QSPI_IP_SUCCESS)
908 {
909 break;
910 }
911
912 /* Clear sequence in LUT registers */
913 Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
914 }
915 if (STATUS_QSPI_IP_SUCCESS == status)
916 {
917 /* Ensure flash is ready after reset */
918 Qspi_Ip_WaitResetComplete();
919 }
920 }
921
922 return status;
923 }
924
925
926 /*FUNCTION**********************************************************************
927 *
928 * Function Name : Qspi_Ip_SerialflashEraseChip
929 * Description : Erase the entire serial flash
930 */
Qspi_Ip_SerialflashEraseChip(uint32 instance)931 static Qspi_Ip_StatusType Qspi_Ip_SerialflashEraseChip(uint32 instance)
932 {
933 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
934 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
935
936 if (state->configuration->eraseSettings.chipEraseLut != QSPI_IP_LUT_INVALID)
937 {
938 /* enable write before erasing */
939 status = Qspi_Ip_WriteEnable(instance);
940 if (STATUS_QSPI_IP_SUCCESS == status)
941 {
942 /* launch erase command */
943 status = Qspi_Ip_RunCommand(instance, state->configuration->eraseSettings.chipEraseLut, 0U);
944 }
945 }
946
947 return status;
948 }
949
950
951 /*FUNCTION**********************************************************************
952 *
953 * Function Name : Qspi_Ip_SerialflashGetMemoryStatus
954 * Description : Get the status of the last operation
955 */
Qspi_Ip_SerialflashGetMemoryStatus(uint32 instance)956 static Qspi_Ip_StatusType Qspi_Ip_SerialflashGetMemoryStatus(uint32 instance)
957 {
958 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
959 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
960 uint8 busyValue = 0xFFU; /* Invalid initial value */
961 Qspi_Ip_StatusType status;
962
963 /* Get the value of busy bit */
964 status = Qspi_Ip_CheckStatusReg(instance, statusConfig->busyOffset, 1U, &busyValue);
965 /* Check BUSY value */
966 if (busyValue == statusConfig->busyValue)
967 {
968 /* Write/erase in progress */
969 status = STATUS_QSPI_IP_BUSY;
970 }
971
972 return status;
973 }
974
975
976 /*FUNCTION**********************************************************************
977 *
978 * Function Name : Qspi_Ip_PatchReadCommand
979 * Description : Patch the command sequence before using
980 */
Qspi_Ip_PatchReadCommand(uint32 instance,uint16 readLut)981 static void Qspi_Ip_PatchReadCommand(uint32 instance,
982 uint16 readLut
983 )
984 {
985 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
986
987 /* Check device type */
988 switch (state->configuration->memType)
989 {
990 case QSPI_IP_HYPER_FLASH:
991 Qspi_Ip_HyperflashPatchReadCommand(instance, readLut);
992 break;
993
994 case QSPI_IP_SERIAL_FLASH:
995 /* Nothing to do with Serial flash */
996 (void)readLut;
997 break;
998
999 default:
1000 (void)readLut; /* unknown operation */
1001 break;
1002 }
1003 }
1004
1005
1006 /*******************************************************************************
1007 * Code
1008 ******************************************************************************/
1009
1010 /*FUNCTION**********************************************************************
1011 *
1012 * Function Name : Qspi_Ip_RunCommand
1013 * Description : Launches a simple command for the serial flash
1014 * @implements Qspi_Ip_RunCommand_Activity */
Qspi_Ip_RunCommand(uint32 instance,uint16 lut,uint32 addr)1015 Qspi_Ip_StatusType Qspi_Ip_RunCommand(uint32 instance,
1016 uint16 lut,
1017 uint32 addr
1018 )
1019 {
1020 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1021 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1022
1023 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1024 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1025 DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1026 DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1027 #endif
1028
1029 if (lut != QSPI_IP_LUT_INVALID)
1030 {
1031 /* Copy sequence in LUT registers */
1032 (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1033
1034 /* Run QSPI command */
1035 status = Qspi_Ip_IpCommand(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr);
1036
1037 /* Clear sequence in LUT registers */
1038 Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1039 }
1040
1041 return status;
1042 }
1043
1044
1045 /*FUNCTION**********************************************************************
1046 *
1047 * Function Name : Qspi_Ip_RunReadCommand
1048 * Description : Launches a read command for the serial flash
1049 * @implements Qspi_Ip_RunReadCommand_Activity */
Qspi_Ip_RunReadCommand(uint32 instance,uint16 lut,uint32 addr,uint8 * dataRead,const uint8 * dataCmp,uint32 size)1050 Qspi_Ip_StatusType Qspi_Ip_RunReadCommand(uint32 instance,
1051 uint16 lut,
1052 uint32 addr,
1053 uint8 * dataRead,
1054 const uint8 * dataCmp,
1055 uint32 size
1056 )
1057 {
1058 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1059 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1060
1061 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1062 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1063 DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1064 DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1065 DEV_ASSERT_QSPI((size > 0UL) && ((addr + size) <= state->configuration->memSize));
1066 #endif
1067
1068 if (lut != QSPI_IP_LUT_INVALID)
1069 {
1070 /* Copy sequence in LUT registers */
1071 (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1072
1073 /* Run QSPI command */
1074 status = Qspi_Ip_IpRead(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr, dataRead, dataCmp, size);
1075
1076 /* Clear sequence in LUT registers */
1077 Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1078 }
1079
1080 return status;
1081 }
1082
1083
1084 /*FUNCTION**********************************************************************
1085 *
1086 * Function Name : Qspi_Ip_RunWriteCommand
1087 * Description : Launches a write command for the serial flash
1088 * @implements Qspi_Ip_RunWriteCommand_Activity */
Qspi_Ip_RunWriteCommand(uint32 instance,uint16 lut,uint32 addr,const uint8 * data,uint32 size)1089 Qspi_Ip_StatusType Qspi_Ip_RunWriteCommand(uint32 instance,
1090 uint16 lut,
1091 uint32 addr,
1092 const uint8 * data,
1093 uint32 size
1094 )
1095 {
1096 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1097 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1098
1099 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1100 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1101 DEV_ASSERT_QSPI(lut != QSPI_IP_LUT_INVALID);
1102 DEV_ASSERT_QSPI(addr < state->configuration->memSize);
1103 DEV_ASSERT_QSPI((size > 0UL) && ((addr + size) <= state->configuration->memSize));
1104 DEV_ASSERT_QSPI(data != NULL_PTR);
1105 #endif
1106
1107 if (lut != QSPI_IP_LUT_INVALID)
1108 {
1109 /* Copy sequence in LUT registers */
1110 (void)Qspi_Ip_InitLutSeq(instance, lut, QSPI_IP_COMMAND_LUT);
1111
1112 /* Run QSPI command */
1113 status = Qspi_Ip_IpWrite(state->connection->qspiInstance, QSPI_IP_COMMAND_LUT, state->baseAddress + addr, data, size);
1114
1115 /* Clear sequence in LUT registers */
1116 Qspi_Ip_DeinitLutSeq(instance, QSPI_IP_COMMAND_LUT);
1117 }
1118
1119 return status;
1120 }
1121
1122
1123
1124 /*FUNCTION**********************************************************************
1125 *
1126 * Function Name : Qspi_Ip_EraseBlock
1127 * Description : Erase a sector in the serial flash.
1128 * The size must match one of the device's erase types.
1129 * @implements Qspi_Ip_EraseBlock_Activity */
Qspi_Ip_EraseBlock(uint32 instance,uint32 address,uint32 size)1130 Qspi_Ip_StatusType Qspi_Ip_EraseBlock(uint32 instance,
1131 uint32 address,
1132 uint32 size
1133 )
1134 {
1135 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1136 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1137 uint8 eraseType;
1138
1139 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1140 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1141 DEV_ASSERT_QSPI(address < state->configuration->memSize);
1142 DEV_ASSERT_QSPI((size > 0UL) && ((address + size) <= state->configuration->memSize));
1143 #endif
1144
1145 /* Check address range */
1146 if (address < state->configuration->memSize)
1147 {
1148 /* find the suited erase type */
1149 for (eraseType = 0U; eraseType < QSPI_IP_ERASE_TYPES; eraseType++)
1150 {
1151 if ((state->configuration->eraseSettings.eraseTypes[eraseType].eraseLut != QSPI_IP_LUT_INVALID) &&
1152 (size == (uint32)((uint32)1U << (state->configuration->eraseSettings.eraseTypes[eraseType].size))))
1153 {
1154 break;
1155 }
1156 }
1157 /* if erase type was found, launch the erase */
1158 if (eraseType < QSPI_IP_ERASE_TYPES)
1159 {
1160 status = Qspi_Ip_BasicErase(instance, address, state->configuration->eraseSettings.eraseTypes[eraseType].eraseLut);
1161 if (STATUS_QSPI_IP_SUCCESS == status)
1162 {
1163 state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1164 }
1165 }
1166 }
1167
1168 return status;
1169 }
1170
1171
1172 /*FUNCTION**********************************************************************
1173 *
1174 * Function Name : Qspi_Ip_EraseChip
1175 * Description : Erase the entire serial flash
1176 * @implements Qspi_Ip_EraseChip_Activity */
Qspi_Ip_EraseChip(uint32 instance)1177 Qspi_Ip_StatusType Qspi_Ip_EraseChip(uint32 instance)
1178 {
1179 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1180 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1181 #endif
1182
1183 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1184 Qspi_Ip_StatusType status;
1185
1186 /* Check device type */
1187 switch (state->configuration->memType)
1188 {
1189 case QSPI_IP_HYPER_FLASH:
1190 status = Qspi_Ip_HyperflashChipErase(instance);
1191 break;
1192
1193 case QSPI_IP_SERIAL_FLASH:
1194 status = Qspi_Ip_SerialflashEraseChip(instance);
1195 break;
1196
1197 default:
1198 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1199 break;
1200 }
1201
1202 if (STATUS_QSPI_IP_SUCCESS == status)
1203 {
1204 state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1205 }
1206
1207 return status;
1208 }
1209
1210
1211 /*FUNCTION**********************************************************************
1212 *
1213 * Function Name : Qspi_Ip_ProgramSuspend
1214 * Description : Suspends a program operation
1215 * @implements Qspi_Ip_ProgramSuspend_Activity */
Qspi_Ip_ProgramSuspend(uint32 instance)1216 Qspi_Ip_StatusType Qspi_Ip_ProgramSuspend(uint32 instance)
1217 {
1218 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1219 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1220 #endif
1221
1222 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1223 Qspi_Ip_StatusType status;
1224
1225 /* Issue the Program Suspend command */
1226 status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.programSuspendLut, 0U);
1227 state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE_SUSPEND;
1228
1229 return status;
1230 }
1231
1232
1233 /*FUNCTION**********************************************************************
1234 *
1235 * Function Name : Qspi_Ip_ProgramResume
1236 * Description : Resumes a program operation
1237 * @implements Qspi_Ip_ProgramResume_Activity */
Qspi_Ip_ProgramResume(uint32 instance)1238 Qspi_Ip_StatusType Qspi_Ip_ProgramResume(uint32 instance)
1239 {
1240 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1241 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1242 #endif
1243
1244 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1245 Qspi_Ip_StatusType status;
1246
1247 /* Issue the Program Resume command */
1248 status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.programResumeLut, 0U);
1249 state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE;
1250
1251 return status;
1252 }
1253
1254
1255 /*FUNCTION**********************************************************************
1256 *
1257 * Function Name : Qspi_Ip_EraseSuspend
1258 * Description : Suspends an erase operation
1259 * @implements Qspi_Ip_EraseSuspend_Activity */
Qspi_Ip_EraseSuspend(uint32 instance)1260 Qspi_Ip_StatusType Qspi_Ip_EraseSuspend(uint32 instance)
1261 {
1262 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1263 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1264 #endif
1265
1266 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1267 Qspi_Ip_StatusType status;
1268
1269 /* Issue the Erase Suspend command */
1270 status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.eraseSuspendLut, 0U);
1271 state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE_SUSPEND;
1272
1273 return status;
1274 }
1275
1276
1277 /*FUNCTION**********************************************************************
1278 *
1279 * Function Name : Qspi_Ip_EraseResume
1280 * Description : Resumes an erase operation
1281 * @implements Qspi_Ip_EraseResume_Activity */
Qspi_Ip_EraseResume(uint32 instance)1282 Qspi_Ip_StatusType Qspi_Ip_EraseResume(uint32 instance)
1283 {
1284 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1285 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1286 #endif
1287
1288 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1289 Qspi_Ip_StatusType status;
1290
1291 /* Issue the Erase Resume command */
1292 status = Qspi_Ip_RunCommand(instance, state->configuration->suspendSettings.eraseResumeLut, 0U);
1293 state->lastCommand = QSPI_IP_LAST_COMMAND_ERASE;
1294
1295 return status;
1296 }
1297
1298
1299 /*FUNCTION**********************************************************************
1300 *
1301 * Function Name : Qspi_Ip_Reset
1302 * Description : Issues a software reset command
1303 * @implements Qspi_Ip_Reset_Activity */
Qspi_Ip_Reset(uint32 instance)1304 Qspi_Ip_StatusType Qspi_Ip_Reset(uint32 instance)
1305 {
1306 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1307 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1308 #endif
1309
1310 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1311 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1312 uint16 resetCmdLut; /*!< First command in reset sequence */
1313 uint8 resetCmdCount; /*!< Number of commands in reset sequence */
1314
1315 resetCmdLut = state->configuration->resetSettings.resetCmdLut;
1316 if (QSPI_IP_LUT_INVALID != resetCmdLut)
1317 {
1318 resetCmdCount = state->configuration->resetSettings.resetCmdCount;
1319 /* Perform reset */
1320 status = Qspi_Ip_InitReset(instance, resetCmdLut, resetCmdCount, state);
1321 /* Bring corresponding controller to initial configuration if required */
1322 if ((STATUS_QSPI_IP_SUCCESS == status) && (state->configuration->ctrlAutoCfgPtr != NULL_PTR))
1323 {
1324 status = Qspi_Ip_ControllerInit(state->connection->qspiInstance, state->configuration->ctrlAutoCfgPtr);
1325 }
1326 if (STATUS_QSPI_IP_SUCCESS == status)
1327 {
1328 /* Execute initial setup of external device */
1329 status = Qspi_Ip_InitDevice(instance, state);
1330 }
1331 }
1332
1333 /* If enabled, call the reset callout. */
1334 if (NULL_PTR != state->configuration->resetCallout)
1335 {
1336 status = state->configuration->resetCallout(instance);
1337 }
1338
1339 return status;
1340 }
1341
1342
1343 /*FUNCTION**********************************************************************
1344 *
1345 * Function Name : Qspi_Ip_GetMemoryStatus
1346 * Description : Get the status of the last operation
1347 * @implements Qspi_Ip_GetMemoryStatus_Activity */
Qspi_Ip_GetMemoryStatus(uint32 instance)1348 Qspi_Ip_StatusType Qspi_Ip_GetMemoryStatus(uint32 instance)
1349 {
1350 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1351 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1352 #endif
1353
1354 Qspi_Ip_StatusType status;
1355 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1356
1357 /* Check if the QuadSPI command is complete */
1358 status = Qspi_Ip_ControllerGetStatus(state->connection->qspiInstance);
1359
1360 if (STATUS_QSPI_IP_SUCCESS == status)
1361 {
1362 /* Check device type */
1363 switch (state->configuration->memType)
1364 {
1365 case QSPI_IP_HYPER_FLASH:
1366 /* Check if the operation has finished in the hyper flash */
1367 status = Qspi_Ip_HyperflashGetMemoryStatus(instance);
1368 break;
1369
1370 case QSPI_IP_SERIAL_FLASH:
1371 /* Check if the operation has finished in the serial flash */
1372 status = Qspi_Ip_SerialflashGetMemoryStatus(instance);
1373 break;
1374 default:
1375 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1376 break;
1377 }
1378 }
1379
1380 if (STATUS_QSPI_IP_SUCCESS == status)
1381 {
1382 /* Call user callout, if available, to check operation result */
1383 if ((state->lastCommand != QSPI_IP_LAST_COMMAND_NONE) && (NULL_PTR != state->configuration->errorCheckCallout))
1384 {
1385 status = state->configuration->errorCheckCallout(instance);
1386 }
1387 state->lastCommand = QSPI_IP_LAST_COMMAND_NONE;
1388 }
1389
1390 return status;
1391 }
1392
1393
1394 /*FUNCTION**********************************************************************
1395 *
1396 * Function Name : Qspi_Ip_CalcPaddingRead
1397 * Description : Calculates the number of padding bytes to handle reading from unaligned addresses
1398 */
Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType * state,uint32 * address,uint32 * size)1399 static inline uint32 Qspi_Ip_CalcPaddingRead(const Qspi_Ip_StateType *state,
1400 uint32 *address,
1401 uint32 *size
1402 )
1403 {
1404 const uint32 qspiInstance = state->connection->qspiInstance;
1405 const uint32 readAlignment = state->connection->memAlignment;
1406
1407 /* Checking for unaligned addresses */
1408 uint32 offset = *address & (readAlignment - 1U);
1409 if (offset != 0U)
1410 {
1411 /* The number of padding bytes to handle unaligned address */
1412 Qspi_Ip_MemoryPadding[qspiInstance] = (uint8)offset;
1413 /* Decreasing the address */
1414 *address -= offset;
1415 /* Increasing the size to compensate */
1416 *size += offset;
1417 }
1418
1419 return offset;
1420 }
1421
1422
1423 /*FUNCTION**********************************************************************
1424 *
1425 * Function Name : Qspi_Ip_Read
1426 * Description : Read data from serial flash
1427 * @implements Qspi_Ip_Read_Activity */
Qspi_Ip_Read(uint32 instance,uint32 address,uint8 * data,uint32 size)1428 Qspi_Ip_StatusType Qspi_Ip_Read(uint32 instance,
1429 uint32 address,
1430 uint8 * data,
1431 uint32 size
1432 )
1433 {
1434 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1435 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1436 uint32 crtAddress = address;
1437 uint8 * crtData = data;
1438 uint32 crtSize = size;
1439 uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1440 uint32 offset;
1441 uint32 ElapsedTicks = 0UL;
1442 uint32 TimeoutTicks;
1443 uint32 CurrentTicks;
1444
1445 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1446 DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1447 DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1448 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1449 DEV_ASSERT_QSPI(data != NULL_PTR);
1450 #endif
1451
1452 /* Checks and handles unaligned addresses */
1453 offset = Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1454
1455 /* Prepare timeout counter */
1456 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1457 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1458 while ((crtSize > 0UL) && (STATUS_QSPI_IP_SUCCESS == status))
1459 {
1460 if (chunkSize > crtSize)
1461 {
1462 /* Adjust size for last chunk */
1463 chunkSize = crtSize;
1464 }
1465 /* Check timeout */
1466 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1467 if (ElapsedTicks >= TimeoutTicks)
1468 {
1469 status = STATUS_QSPI_IP_TIMEOUT;
1470 break;
1471 }
1472
1473 /* Patch the command sequence before using */
1474 Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1475 status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, crtData, NULL_PTR, chunkSize);
1476 /* Move to next chunk */
1477 crtSize -= chunkSize;
1478 crtAddress += chunkSize;
1479 crtData = &(crtData[chunkSize - offset]); /* Handle alignment for the first read */
1480 offset = 0U;
1481
1482 /* Call user callout, if available, to check ECC or CRC status */
1483 if ((STATUS_QSPI_IP_SUCCESS == status) && (NULL_PTR != state->configuration->eccCheckCallout))
1484 {
1485 status = state->configuration->eccCheckCallout(instance, crtAddress, chunkSize);
1486 }
1487 }
1488 return status;
1489 }
1490
1491
1492 /*FUNCTION**********************************************************************
1493 *
1494 * Function Name : Qspi_Ip_ReadId
1495 * Description : Read manufacturer ID from serial flash
1496 * @implements Qspi_Ip_ReadId_Activity */
Qspi_Ip_ReadId(uint32 instance,uint8 * data)1497 Qspi_Ip_StatusType Qspi_Ip_ReadId(uint32 instance,
1498 uint8 * data
1499 )
1500 {
1501 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1502 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1503 DEV_ASSERT_QSPI(data != NULL_PTR);
1504 #endif
1505
1506 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1507 Qspi_Ip_StatusType status;
1508
1509 /* Check device type */
1510 switch (state->configuration->memType)
1511 {
1512 case QSPI_IP_HYPER_FLASH:
1513 status = Qspi_Ip_HyperflashReadId(instance,
1514 state->configuration->hfConfig->deviceIdWordAddress,
1515 data,
1516 state->configuration->readIdSettings.readIdSize);
1517 break;
1518
1519 case QSPI_IP_SERIAL_FLASH:
1520 status = Qspi_Ip_RunReadCommand(instance,
1521 state->configuration->readIdSettings.readIdLut,
1522 0U,
1523 data,
1524 NULL_PTR,
1525 state->configuration->readIdSettings.readIdSize);
1526 break;
1527 default:
1528 status = STATUS_QSPI_IP_ERROR; /* unknown operation */
1529 break;
1530 }
1531
1532 return status;
1533 }
1534
1535
1536 /*FUNCTION**********************************************************************
1537 *
1538 * Function Name : Qspi_Ip_ProgramVerify
1539 * Description : Verifies data written in serial flash
1540 * @implements Qspi_Ip_ProgramVerify_Activity */
Qspi_Ip_ProgramVerify(uint32 instance,uint32 address,const uint8 * data,uint32 size)1541 Qspi_Ip_StatusType Qspi_Ip_ProgramVerify(uint32 instance,
1542 uint32 address,
1543 const uint8 * data,
1544 uint32 size
1545 )
1546 {
1547 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1548 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1549 uint32 crtAddress = address;
1550 const uint8 * crtData = data;
1551 uint32 crtSize = size;
1552 uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1553 uint32 offset;
1554 uint32 ElapsedTicks = 0UL;
1555 uint32 TimeoutTicks;
1556 uint32 CurrentTicks;
1557
1558 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1559 DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1560 DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1561 DEV_ASSERT_QSPI(data != NULL_PTR);
1562 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1563 #endif
1564
1565 /* Checks and handles unaligned addresses */
1566 offset = Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1567
1568 /* Prepare timeout counter */
1569 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1570 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1571 while ((crtSize > 0U) && (STATUS_QSPI_IP_SUCCESS == status))
1572 {
1573 if (chunkSize > crtSize)
1574 {
1575 /* Adjust size for last chunk */
1576 chunkSize = crtSize;
1577 }
1578 /* Check timeout */
1579 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1580 if (ElapsedTicks >= TimeoutTicks)
1581 {
1582 status = STATUS_QSPI_IP_TIMEOUT;
1583 break;
1584 }
1585
1586 /* Patch the command sequence before using */
1587 Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1588 status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, NULL_PTR, crtData, chunkSize);
1589 /* Move to next chunk */
1590 crtSize -= chunkSize;
1591 crtAddress += chunkSize;
1592 crtData = &(crtData[chunkSize - offset]); /* Handle alignment for the first read */
1593 offset = 0U;
1594 }
1595 return status;
1596 }
1597
1598
1599
1600 /*FUNCTION**********************************************************************
1601 *
1602 * Function Name : Qspi_Ip_EraseVerify
1603 * Description : Verifies that an area in serial flash is in erased state
1604 * @implements Qspi_Ip_EraseVerify_Activity */
Qspi_Ip_EraseVerify(uint32 instance,uint32 address,uint32 size)1605 Qspi_Ip_StatusType Qspi_Ip_EraseVerify(uint32 instance,
1606 uint32 address,
1607 uint32 size
1608 )
1609 {
1610 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1611 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1612 uint32 crtAddress = address;
1613 uint32 crtSize = size;
1614 uint32 chunkSize = QSPI_IP_MAX_READ_SIZE;
1615 uint32 ElapsedTicks = 0UL;
1616 uint32 TimeoutTicks;
1617 uint32 CurrentTicks;
1618
1619 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1620 DEV_ASSERT_QSPI(crtAddress < state->configuration->memSize);
1621 DEV_ASSERT_QSPI((crtSize > 0UL) && ((crtAddress + crtSize) <= state->configuration->memSize));
1622 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1623 #endif
1624
1625 /* Checks and handles unaligned addresses */
1626 (void)Qspi_Ip_CalcPaddingRead(state, &crtAddress, &crtSize);
1627
1628 /* Prepare timeout counter */
1629 TimeoutTicks = OsIf_MicrosToTicks(QSPI_IP_READ_TIMEOUT, QSPI_IP_TIMEOUT_TYPE);
1630 CurrentTicks = OsIf_GetCounter(QSPI_IP_TIMEOUT_TYPE);
1631 while ((crtSize > 0UL) && (STATUS_QSPI_IP_SUCCESS == status))
1632 {
1633 if (chunkSize > crtSize)
1634 {
1635 /* Adjust size for last chunk */
1636 chunkSize = crtSize;
1637 }
1638 /* Check timeout */
1639 ElapsedTicks += OsIf_GetElapsed(&CurrentTicks, QSPI_IP_TIMEOUT_TYPE);
1640 if (ElapsedTicks >= TimeoutTicks)
1641 {
1642 status = STATUS_QSPI_IP_TIMEOUT;
1643 break;
1644 }
1645
1646 /* Patch the command sequence before issuing */
1647 Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1648 status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, crtAddress, NULL_PTR, NULL_PTR, chunkSize);
1649 /* Move to next chunk */
1650 crtSize -= chunkSize;
1651 crtAddress += chunkSize;
1652 }
1653 return status;
1654 }
1655
1656
1657 /*FUNCTION**********************************************************************
1658 *
1659 * Function Name : Qspi_Ip_CalcPaddingWrite
1660 * Description : Calculates the number of padding bytes to handle writing to unaligned addresses
1661 */
Qspi_Ip_CalcPaddingWrite(const Qspi_Ip_StateType * state,uint32 address,uint32 size)1662 static inline uint32 Qspi_Ip_CalcPaddingWrite(const Qspi_Ip_StateType *state,
1663 uint32 address,
1664 uint32 size
1665 )
1666 {
1667 uint32 qspiInstance = state->connection->qspiInstance;
1668 uint32 alignmentMask = (uint32)(state->connection->memAlignment) - 1UL;
1669
1670 /* The number of pre-padding bytes */
1671 uint32 prePadding = address & alignmentMask;
1672
1673 /* The number of post-padding bytes */
1674 uint32 endAddr = address + size - 1UL;
1675 uint32 postPadding = alignmentMask - (endAddr & alignmentMask);
1676
1677 /* Store padding information */
1678 Qspi_Ip_MemoryPadding[qspiInstance] = (uint8)((prePadding << 4UL) | postPadding);
1679
1680 /* Decreasing the address */
1681 return (address - prePadding);
1682 }
1683
1684
1685 /*FUNCTION**********************************************************************
1686 *
1687 * Function Name : Qspi_Ip_Program
1688 * Description : Writes data in serial flash
1689 * @implements Qspi_Ip_Program_Activity */
Qspi_Ip_Program(uint32 instance,uint32 address,const uint8 * data,uint32 size)1690 Qspi_Ip_StatusType Qspi_Ip_Program(uint32 instance,
1691 uint32 address,
1692 const uint8 * data,
1693 uint32 size
1694 )
1695 {
1696 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1697 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1698 uint32 alignedAddress;
1699
1700 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1701 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1702 DEV_ASSERT_QSPI(address < state->configuration->memSize);
1703 DEV_ASSERT_QSPI(data != NULL_PTR);
1704 DEV_ASSERT_QSPI((size > 0UL) && ((address + size) <= state->configuration->memSize));
1705 #endif
1706
1707 /* Check address range and page size */
1708 if ((address < state->configuration->memSize) && ((size <= state->configuration->pageSize)))
1709 {
1710 /* Write data to the flash device */
1711 switch (state->configuration->memType)
1712 {
1713 case QSPI_IP_HYPER_FLASH:
1714 /* Perform alignment checking before write data */
1715 alignedAddress = Qspi_Ip_CalcPaddingWrite(state, address, size);
1716 /* Write data to hyper flash */
1717 status = Qspi_Ip_HyperflashProgram(instance, alignedAddress, data, size);
1718 break;
1719
1720 case QSPI_IP_SERIAL_FLASH:
1721 /* enable write before programming */
1722 status = Qspi_Ip_WriteEnable(instance);
1723 if (STATUS_QSPI_IP_SUCCESS == status)
1724 {
1725 /* Perform alignment checking before write data */
1726 alignedAddress = Qspi_Ip_CalcPaddingWrite(state, address, size);
1727 /* Write data to serial flash */
1728 status = Qspi_Ip_RunWriteCommand(instance, state->configuration->writeLut, alignedAddress, data, size);
1729 }
1730 break;
1731 default:
1732 status = STATUS_QSPI_IP_ERROR;
1733 break;
1734 }
1735
1736 if (STATUS_QSPI_IP_SUCCESS == status)
1737 {
1738 state->lastCommand = QSPI_IP_LAST_COMMAND_WRITE;
1739 }
1740 }
1741
1742 return status;
1743 }
1744
1745
1746 /*FUNCTION**********************************************************************
1747 *
1748 * Function Name : Qspi_Ip_Enter0XX
1749 * Description : Enters 0-X-X mode (no command for read instructions)
1750 * @implements Qspi_Ip_Enter0XX_Activity */
Qspi_Ip_Enter0XX(uint32 instance)1751 Qspi_Ip_StatusType Qspi_Ip_Enter0XX(uint32 instance)
1752 {
1753 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1754 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1755 #endif
1756
1757 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1758 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1759 uint8 dummyData;
1760
1761 if (state->configuration->read0xxLut != QSPI_IP_LUT_INVALID)
1762 {
1763 state->activeReadLut = state->configuration->read0xxLut;
1764 /* Perform a dummy read to activate 0-X-X mode */
1765 status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, 0U, &dummyData, NULL_PTR, 1U);
1766 }
1767
1768 if (state->configuration->read0xxLutAHB != QSPI_IP_LUT_INVALID)
1769 {
1770 /* Set 0-x-x mode LUT sequence for AHB */
1771 (void)Qspi_Ip_InitLutSeq(instance, state->configuration->read0xxLutAHB, QSPI_IP_AHB_LUT);
1772 }
1773
1774 return status;
1775 }
1776
1777
1778 /*FUNCTION**********************************************************************
1779 *
1780 * Function Name : Qspi_Ip_Exit0XX
1781 * Description : Exits 0-X-X mode (no command for read instructions)
1782 * @implements Qspi_Ip_Exit0XX_Activity */
Qspi_Ip_Exit0XX(uint32 instance)1783 Qspi_Ip_StatusType Qspi_Ip_Exit0XX(uint32 instance)
1784 {
1785 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1786 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1787 #endif
1788
1789 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1790 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1791 uint8 dummyData;
1792
1793 if (state->configuration->read0xxLut != QSPI_IP_LUT_INVALID)
1794 {
1795 state->activeReadLut = state->configuration->readLut;
1796 /* Perform a dummy read to disable 0-X-X mode */
1797 status = Qspi_Ip_RunReadCommand(instance, state->activeReadLut, 0U, &dummyData, NULL_PTR, 1U);
1798 }
1799
1800 if (state->configuration->read0xxLutAHB != QSPI_IP_LUT_INVALID)
1801 {
1802 /* Set back to normal mode LUT sequence for AHB */
1803 (void)Qspi_Ip_InitLutSeq(instance, state->configuration->readLut, QSPI_IP_AHB_LUT);
1804 }
1805
1806 return status;
1807 }
1808
1809
1810 /*FUNCTION**********************************************************************
1811 *
1812 * Function Name : Qspi_Ip_SetProtection
1813 * Description : Sets the protection bits of the device
1814 * @implements Qspi_Ip_SetProtection_Activity */
Qspi_Ip_SetProtection(uint32 instance,uint8 value)1815 Qspi_Ip_StatusType Qspi_Ip_SetProtection(uint32 instance,
1816 uint8 value
1817 )
1818 {
1819 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1820 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1821 #endif
1822
1823 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1824 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
1825
1826 return Qspi_Ip_UpdateStatusReg(instance, statusConfig->blockProtectionOffset, statusConfig->blockProtectionWidth, value);
1827 }
1828
1829
1830 /*FUNCTION**********************************************************************
1831 *
1832 * Function Name : Qspi_Ip_GetProtection
1833 * Description : Returns the current protection bits of the device
1834 * @implements Qspi_Ip_GetProtection_Activity */
Qspi_Ip_GetProtection(uint32 instance,uint8 * value)1835 Qspi_Ip_StatusType Qspi_Ip_GetProtection(uint32 instance,
1836 uint8 *value
1837 )
1838 {
1839 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1840 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1841 DEV_ASSERT_QSPI(value != NULL_PTR);
1842 #endif
1843
1844 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1845 const Qspi_Ip_StatusConfigType *statusConfig = &(state->configuration->statusConfig);
1846
1847 return Qspi_Ip_CheckStatusReg(instance, statusConfig->blockProtectionOffset, statusConfig->blockProtectionWidth, value);
1848 }
1849
1850
1851 /*FUNCTION**********************************************************************
1852 *
1853 * Function Name : Qspi_Ip_AhbReadEnable
1854 * Description : Enables AHB reads for the current flash device
1855 * @implements Qspi_Ip_AhbReadEnable_Activity */
Qspi_Ip_AhbReadEnable(uint32 instance)1856 Qspi_Ip_StatusType Qspi_Ip_AhbReadEnable(uint32 instance)
1857 {
1858 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1859 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1860 #endif
1861
1862 Qspi_Ip_StatusType status = STATUS_QSPI_IP_ERROR;
1863 const Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1864
1865 if (state->activeReadLut != QSPI_IP_LUT_INVALID)
1866 {
1867 /* Patch the command sequence before using */
1868 Qspi_Ip_PatchReadCommand(instance, state->activeReadLut);
1869 /* Copy sequence in LUT registers */
1870 (void)Qspi_Ip_InitLutSeq(instance, state->activeReadLut, QSPI_IP_AHB_LUT);
1871 /* Set sequence number */
1872 Qspi_Ip_SetAhbSeqId(state->connection->qspiInstance, QSPI_IP_AHB_LUT);
1873 status = STATUS_QSPI_IP_SUCCESS;
1874 }
1875
1876 return status;
1877 }
1878
1879
1880 /*FUNCTION**********************************************************************
1881 *
1882 * Function Name : Qspi_Ip_Init
1883 * Description : Initialize the serial flash memory driver
1884 *
1885 * @implements Qspi_Ip_Init_Activity */
Qspi_Ip_Init(uint32 instance,const Qspi_Ip_MemoryConfigType * pConfig,const Qspi_Ip_MemoryConnectionType * pConnect)1886 Qspi_Ip_StatusType Qspi_Ip_Init(uint32 instance,
1887 const Qspi_Ip_MemoryConfigType * pConfig,
1888 const Qspi_Ip_MemoryConnectionType * pConnect
1889 )
1890 {
1891 Qspi_Ip_StatusType status = STATUS_QSPI_IP_SUCCESS;
1892 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1893
1894 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1895 DEV_ASSERT_QSPI(instance < QSPI_IP_MEM_INSTANCE_COUNT);
1896 DEV_ASSERT_QSPI(pConfig != NULL_PTR);
1897 DEV_ASSERT_QSPI(pConnect != NULL_PTR);
1898 DEV_ASSERT_QSPI(NULL_PTR == state->configuration);
1899 #endif
1900
1901 /* Copy configuration information to state structure */
1902 state->configuration = pConfig;
1903 state->connection = pConnect;
1904 state->activeReadLut = pConfig->readLut; /* 0-X-X mode disabled by default */
1905 state->lastCommand = QSPI_IP_LAST_COMMAND_NONE;
1906 state->baseAddress = Qspi_Ip_GetBaseAdress(pConnect->qspiInstance, pConnect->connectionType);
1907
1908 #if (QSPI_PERFORM_DEVICE_CONFIG == STD_ON)
1909 /* Initialize corresponding controller if required */
1910 if (pConfig->ctrlAutoCfgPtr != NULL_PTR)
1911 {
1912 status = Qspi_Ip_ControllerInit(pConnect->qspiInstance, pConfig->ctrlAutoCfgPtr);
1913 }
1914 if (STATUS_QSPI_IP_SUCCESS == status)
1915 {
1916 /* Perform initial reset */
1917 status = Qspi_Ip_InitReset(instance, pConfig->initResetSettings.resetCmdLut, pConfig->initResetSettings.resetCmdCount, state);
1918 }
1919 if (STATUS_QSPI_IP_SUCCESS == status)
1920 {
1921 /* Execute initial setup of external device */
1922 status = Qspi_Ip_InitDevice(instance, state);
1923 }
1924
1925 /* If enabled, call the init callout, for additional QSPI IP or external memory settings. */
1926 if ((STATUS_QSPI_IP_SUCCESS == status) && (NULL_PTR != pConfig->initCallout))
1927 {
1928 status = pConfig->initCallout(instance);
1929 }
1930
1931 /* Perform protection configuration */
1932 if (STATUS_QSPI_IP_SUCCESS == status)
1933 {
1934 status = Qspi_Ip_InitProtection(instance, state);
1935 }
1936 #endif
1937
1938 return status;
1939 }
1940
1941
1942 /*FUNCTION**********************************************************************
1943 *
1944 * Function Name : Qspi_Ip_Deinit
1945 * Description : De-initialize the serial flash memory driver
1946 * @implements Qspi_Ip_Deinit_Activity */
Qspi_Ip_Deinit(uint32 instance)1947 Qspi_Ip_StatusType Qspi_Ip_Deinit(uint32 instance)
1948 {
1949 Qspi_Ip_StateType * state = &(Qspi_Ip_MemoryStateStructure[instance]);
1950 #if (QSPI_IP_DEV_ERROR_DETECT == STD_ON)
1951 DEV_ASSERT_QSPI(instance < QuadSPI_INSTANCE_COUNT);
1952 DEV_ASSERT_QSPI(state->configuration != NULL_PTR);
1953 #endif
1954
1955 state->configuration = NULL_PTR;
1956 return STATUS_QSPI_IP_SUCCESS;
1957 }
1958
1959 #define MEM_43_EXFLS_STOP_SEC_CODE
1960 #include "Mem_43_EXFLS_MemMap.h"
1961
1962 #endif /* (QSPI_IP_MEM_INSTANCE_COUNT > 0) */
1963
1964
1965 #ifdef __cplusplus
1966 }
1967 #endif
1968
1969 /** @} */
1970
1971