1 /***************************************************************************//**
2 * \file cy_flash.c
3 * \version 3.70
4 *
5 * \brief
6 * Provides the public functions for the API for the PSoC 6 Flash Driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2021 Cypress Semiconductor Corporation
11 * SPDX-License-Identifier: Apache-2.0
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *******************************************************************************/
25
26 #include "cy_device.h"
27
28 #if defined (CY_IP_M4CPUSS)
29
30 #include "cy_flash.h"
31 #include "cy_sysclk.h"
32 #include "cy_sysint.h"
33 #include "cy_ipc_drv.h"
34 #include "cy_ipc_sema.h"
35 #include "cy_ipc_pipe.h"
36 #include "cy_syslib.h"
37 #if defined (CY_DEVICE_SECURE)
38 #include "cy_pra.h"
39 #endif /* defined (CY_DEVICE_SECURE) */
40
41 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 2, \
42 'IPC_STRUCT_Type will typecast to either IPC_STRUCT_V1_Type or IPC_STRUCT_V2_Type but not both on PDL initialization based on the target device at compile time.')
43
44 /***************************************
45 * Data Structure definitions
46 ***************************************/
47
48 /* Flash driver context */
49 typedef struct
50 {
51 uint32_t opcode; /**< Specifies the code of flash operation */
52 uint32_t arg1; /**< Specifies the configuration of flash operation */
53 uint32_t arg2; /**< Specifies the configuration of flash operation */
54 uint32_t arg3; /**< Specifies the configuration of flash operation */
55 } cy_stc_flash_context_t;
56
57
58 /***************************************
59 * Macro definitions
60 ***************************************/
61
62 /** \cond INTERNAL */
63 /** Set SROM API in blocking mode */
64 #define CY_FLASH_BLOCKING_MODE ((0x01UL) << 8UL)
65 /** Set SROM API in non blocking mode */
66 #define CY_FLASH_NON_BLOCKING_MODE (0UL)
67
68 /** SROM API flash region ID shift for flash row information */
69 #define CY_FLASH_REGION_ID_SHIFT (16U)
70 #define CY_FLASH_REGION_ID_MASK (3U)
71 #define CY_FLASH_ROW_ID_MASK (0xFFFFU)
72 /** SROM API flash region IDs */
73 #define CY_FLASH_REGION_ID_MAIN (0UL)
74 #define CY_FLASH_REGION_ID_EM_EEPROM (1UL)
75 #define CY_FLASH_REGION_ID_SFLASH (2UL)
76
77 /** SROM API opcode mask */
78 #define CY_FLASH_OPCODE_Msk ((0xFFUL) << 24UL)
79 /** SROM API opcode for flash write operation */
80 #define CY_FLASH_OPCODE_WRITE_ROW ((0x05UL) << 24UL)
81 /** SROM API opcode for flash program operation */
82 #define CY_FLASH_OPCODE_PROGRAM_ROW ((0x06UL) << 24UL)
83 /** SROM API opcode for row erase operation */
84 #define CY_FLASH_OPCODE_ERASE_ROW ((0x1CUL) << 24UL)
85 /** SROM API opcode for sub sector erase operation */
86 #define CY_FLASH_OPCODE_ERASE_SUB_SECTOR ((0x1DUL) << 24UL)
87 /** SROM API opcode for sector erase operation */
88 #define CY_FLASH_OPCODE_ERASE_SECTOR ((0x14UL) << 24UL)
89 /** SROM API opcode for flash checksum operation */
90 #define CY_FLASH_OPCODE_CHECKSUM ((0x0BUL) << 24UL)
91 /** SROM API opcode for flash hash operation */
92 #define CY_FLASH_OPCODE_HASH ((0x0DUL) << 24UL)
93 /** SROM API flash row shift for flash checksum operation */
94 #define CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT (8UL)
95 /** SROM API flash row shift for flash checksum operation */
96 #define CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT (22UL)
97 /** Data to be programmed to flash is located in SRAM memory region */
98 #define CY_FLASH_DATA_LOC_SRAM (0x100UL)
99 /** SROM API flash verification option for flash write operation */
100 #define CY_FLASH_CONFIG_VERIFICATION_EN ((0x01UL) << 16u)
101
102 /** Command completed with no errors */
103 #define CY_FLASH_ROMCODE_SUCCESS (0xA0000000UL)
104 /** Invalid device protection state */
105 #define CY_FLASH_ROMCODE_INVALID_PROTECTION (0xF0000001UL)
106 /** Invalid flash page latch address */
107 #define CY_FLASH_ROMCODE_INVALID_FM_PL (0xF0000003UL)
108 /** Invalid flash address */
109 #define CY_FLASH_ROMCODE_INVALID_FLASH_ADDR (0xF0000004UL)
110 /** Row is write protected */
111 #define CY_FLASH_ROMCODE_ROW_PROTECTED (0xF0000005UL)
112 /** Comparison between Page Latches and FM row failed */
113 #define CY_FLASH_ROMCODE_PL_ROW_COMP_FA (0xF0000022UL)
114 /** Command in progress; no error */
115 #define CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR (0xA0000009UL)
116 /** Flash operation is successfully initiated */
117 #define CY_FLASH_IS_OPERATION_STARTED (0x00000010UL)
118 /** Flash is under operation */
119 #define CY_FLASH_IS_BUSY (0x00000040UL)
120 /** IPC structure is already locked by another process */
121 #define CY_FLASH_IS_IPC_BUSY (0x00000080UL)
122 /** Input parameters passed to Flash API are not valid */
123 #define CY_FLASH_IS_INVALID_INPUT_PARAMETERS (0x00000100UL)
124
125 /** Result mask */
126 #define CY_FLASH_RESULT_MASK (0x0FFFFFFFUL)
127 /** Error shift */
128 #define CY_FLASH_ERROR_SHIFT (28UL)
129 /** No error */
130 #define CY_FLASH_ERROR_NO_ERROR (0xAUL)
131
132 /** CM4 Flash Proxy address */
133 #define CY_FLASH_CM4_FLASH_PROXY_ADDR (*(Cy_Flash_Proxy *)(0x00000D1CUL))
134 typedef cy_en_flashdrv_status_t (*Cy_Flash_Proxy)(cy_stc_flash_context_t *context);
135
136 /** IPC notify bit for IPC0 structure (dedicated to flash operation) */
137 #define CY_FLASH_IPC_NOTIFY_STRUCT0 (0x1UL << CY_IPC_INTR_SYSCALL1)
138
139 /** Disable delay */
140 #define CY_FLASH_NO_DELAY (0U)
141
142 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
143 /** Number of ticks to wait 1 uS */
144 #define CY_FLASH_TICKS_FOR_1US (8U)
145 /** Define to set the IMO to perform a delay after the flash operation started */
146 #define CY_FLASH_TST_DDFT_SLOW_CTL_MASK (0x00001F1EUL)
147 /** Fast control register */
148 #define CY_FLASH_TST_DDFT_FAST_CTL_MASK (62U)
149 /** Slow output register - output disabled */
150 #define CY_FLASH_CLK_OUTPUT_DISABLED (0U)
151
152 /* The default delay time value */
153 #define CY_FLASH_DEFAULT_DELAY (150UL)
154 /* Calculates the time in microseconds to wait for the number of the CM0P ticks */
155 #define CY_FLASH_DELAY_CORRECTIVE(ticks) (((ticks) * 1000UL) / (Cy_SysClk_ClkSlowGetFrequency() / 1000UL))
156
157 /* Number of the CM0P ticks for StartProgram function delay corrective time */
158 #define CY_FLASH_START_PROGRAM_DELAY_TICKS (6000UL)
159 /* Delay time for StartProgram function in us */
160 #define CY_FLASH_START_PROGRAM_DELAY_TIME (900UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_PROGRAM_DELAY_TICKS))
161 /* Number of the CM0P ticks for StartErase functions delay corrective time */
162 #define CY_FLASH_START_ERASE_DELAY_TICKS (9500UL)
163 /* Delay time for StartErase functions in us */
164 #define CY_FLASH_START_ERASE_DELAY_TIME (2200UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_ERASE_DELAY_TICKS))
165 /* Number of the CM0P ticks for StartWrite function delay corrective time */
166 #define CY_FLASH_START_WRITE_DELAY_TICKS (19000UL)
167 /* Delay time for StartWrite function in us */
168 #define CY_FLASH_START_WRITE_DELAY_TIME (9800UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_START_WRITE_DELAY_TICKS))
169
170 /** Delay time for Start Write function in us with corrective time */
171 #define CY_FLASH_START_WRITE_DELAY (CY_FLASH_START_WRITE_DELAY_TIME)
172 /** Delay time for Start Program function in us with corrective time */
173 #define CY_FLASH_START_PROGRAM_DELAY (CY_FLASH_START_PROGRAM_DELAY_TIME)
174 /** Delay time for Start Erase function in uS with corrective time */
175 #define CY_FLASH_START_ERASE_DELAY (CY_FLASH_START_ERASE_DELAY_TIME)
176
177 #define CY_FLASH_ENTER_WAIT_LOOP (0xFFU)
178 #define CY_FLASH_IPC_CLIENT_ID (2U)
179
180 /** Semaphore number reserved for flash driver */
181 #define CY_FLASH_WAIT_SEMA (0UL)
182 /* Semaphore check timeout (in tries) */
183 #define CY_FLASH_SEMA_WAIT_MAX_TRIES (150000UL)
184
185 static void Cy_Flash_RAMDelay(uint32_t microseconds);
186
187 #if (CY_CPU_CORTEX_M0P)
188 #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP1)))
189 #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM4_ADDR, CY_IPC_EP_CYPIPE_CM0_ADDR, (a), NULL)
190 #else
191 #define IS_CY_PIPE_FREE(...) (!Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0)))
192 #define NOTIFY_PEER_CORE(a) Cy_IPC_Pipe_SendMessage(CY_IPC_EP_CYPIPE_CM0_ADDR, CY_IPC_EP_CYPIPE_CM4_ADDR, (a), NULL)
193 #endif
194
195 static void Cy_Flash_NotifyHandler(uint32_t * msgPtr);
196
197 static cy_stc_flash_notify_t * ipcWaitMessage;
198
199 #else
200 /** Delay time for Start Write function in us with corrective time */
201 #define CY_FLASH_START_WRITE_DELAY (CY_FLASH_NO_DELAY)
202 /** Delay time for Start Program function in us with corrective time */
203 #define CY_FLASH_START_PROGRAM_DELAY (CY_FLASH_NO_DELAY)
204 /** Delay time for Start Erase function in uS with corrective time */
205 #define CY_FLASH_START_ERASE_DELAY (CY_FLASH_NO_DELAY)
206
207 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
208 /** \endcond */
209
210 /* Static functions */
211 static bool Cy_Flash_BoundsCheck(uint32_t flashAddr);
212 static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr);
213 static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode);
214 static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void);
215 static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds);
216
217 static volatile cy_stc_flash_context_t flashContext;
218
219
220 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
221 /*******************************************************************************
222 * Function Name: Cy_Flash_InitExt
223 ****************************************************************************//**
224 *
225 * Initiates all needed prerequisites to support flash erase/write.
226 * Should be called from each core. Defines the address of the message structure.
227 *
228 * Requires a call to Cy_IPC_Sema_Init(), Cy_IPC_Pipe_Config() and
229 * Cy_IPC_Pipe_Init() functions before use.
230 *
231 * This function is called in the Cy_Flash_Init() function - see the
232 * Cy_Flash_Init usage considerations.
233 *
234 *******************************************************************************/
Cy_Flash_InitExt(cy_stc_flash_notify_t * ipcWaitMessageAddr)235 void Cy_Flash_InitExt(cy_stc_flash_notify_t *ipcWaitMessageAddr)
236 {
237 ipcWaitMessage = ipcWaitMessageAddr;
238
239 if(ipcWaitMessage != NULL)
240 {
241 ipcWaitMessage->clientID = CY_FLASH_IPC_CLIENT_ID;
242 ipcWaitMessage->pktType = CY_FLASH_ENTER_WAIT_LOOP;
243 ipcWaitMessage->intrRelMask = 0U;
244 }
245
246 if (cy_device->flashRwwRequired != 0U)
247 {
248 #if (CY_CPU_CORTEX_M4)
249 cy_stc_sysint_t flashIntConfig =
250 {
251 (IRQn_Type)cy_device->cpussFmIrq, /* .intrSrc */
252 0U /* .intrPriority */
253 };
254
255 (void)Cy_SysInt_Init(&flashIntConfig, &Cy_Flash_ResumeIrqHandler);
256 NVIC_EnableIRQ(flashIntConfig.intrSrc);
257 #endif
258
259 if (cy_device->flashPipeRequired != 0U)
260 {
261 (void)Cy_IPC_Pipe_RegisterCallback(CY_IPC_EP_CYPIPE_ADDR, &Cy_Flash_NotifyHandler,
262 (uint32_t)CY_FLASH_IPC_CLIENT_ID);
263 }
264 }
265 }
266
267
268 /*******************************************************************************
269 * Function Name: Cy_Flash_NotifyHandler
270 ****************************************************************************//**
271 *
272 * This is the interrupt service routine for the pipe notifications.
273 *
274 *******************************************************************************/
275 CY_SECTION_RAMFUNC_BEGIN
276 #if !defined (__ICCARM__)
277 CY_NOINLINE
278 #endif
Cy_Flash_NotifyHandler(uint32_t * msgPtr)279 static void Cy_Flash_NotifyHandler(uint32_t * msgPtr)
280 {
281 #if !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE)))
282 uint32_t intr;
283 #endif /* !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE))) */
284 static uint32_t semaIndex;
285 static uint32_t semaMask;
286 static volatile uint32_t *semaPtr;
287 static cy_stc_ipc_sema_t *semaStruct;
288
289 cy_stc_flash_notify_t *ipcMsgPtr = (cy_stc_flash_notify_t *) (void *) msgPtr;
290
291 if (CY_FLASH_ENTER_WAIT_LOOP == ipcMsgPtr->pktType)
292 {
293 #if !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE)))
294 intr = Cy_SysLib_EnterCriticalSection();
295 #endif /* !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE))) */
296
297 /* Get pointer to structure */
298 semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SEMA));
299
300 /* Get the index into the semaphore array and calculate the mask */
301 semaIndex = CY_FLASH_WAIT_SEMA / CY_IPC_SEMA_PER_WORD;
302 semaMask = (uint32_t)(1UL << (CY_FLASH_WAIT_SEMA - (semaIndex * CY_IPC_SEMA_PER_WORD) ));
303 semaPtr = &semaStruct->arrayPtr[semaIndex];
304
305 /* Notification to the Flash driver to start the current operation */
306 *semaPtr |= semaMask;
307
308 /* Check a notification from other core to end of waiting */
309 while (((*semaPtr) & semaMask) != 0UL)
310 {
311 }
312
313 #if !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE)))
314 Cy_SysLib_ExitCriticalSection(intr);
315 #endif /* !((CY_CPU_CORTEX_M0P) && (defined (CY_DEVICE_SECURE))) */
316 }
317 }
318 CY_SECTION_RAMFUNC_END
319 #endif /* !defined(CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
320
321
322 /*******************************************************************************
323 * Function Name: Cy_Flash_Init
324 ****************************************************************************//**
325 *
326 * Initiates all needed prerequisites to support flash erase/write.
327 * Should be called from each core.
328 *
329 * Requires a call to Cy_IPC_Sema_Init(), Cy_IPC_Pipe_Config() and
330 * Cy_IPC_Pipe_Init() functions before use.
331 *
332 * This function is called in the SystemInit() function, for proper flash write
333 * and erase operations. If the default startup file is not used, or the function
334 * SystemInit() is not called in your project, ensure to perform the following steps
335 * before any flash or EmEEPROM write/erase operations:
336 *
337 *******************************************************************************/
Cy_Flash_Init(void)338 void Cy_Flash_Init(void)
339 {
340 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
341 CY_SECTION_SHAREDMEM
342 static cy_stc_flash_notify_t ipcWaitMessageStc CY_ALIGN(4);
343
344 Cy_Flash_InitExt(&ipcWaitMessageStc);
345 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
346 }
347
348
349 /*******************************************************************************
350 * Function Name: Cy_Flash_SendCmd
351 ****************************************************************************//**
352 *
353 * Sends a command to the SROM via the IPC channel. The function is placed to the
354 * SRAM memory to guarantee successful operation. After an IPC message is sent,
355 * the function waits for a defined time before exiting the function.
356 *
357 *******************************************************************************/
358 CY_SECTION_RAMFUNC_BEGIN
359 #if !defined (__ICCARM__)
360 CY_NOINLINE
361 #endif
Cy_Flash_SendCmd(uint32_t mode,uint32_t microseconds)362 static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds)
363 {
364 cy_en_flashdrv_status_t result = CY_FLASH_DRV_IPC_BUSY;
365 IPC_STRUCT_Type * locIpcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL);
366 volatile uint32_t *ipcLockStatus = ®_IPC_STRUCT_LOCK_STATUS(locIpcBase);
367
368 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
369 uint32_t intr;
370 uint32_t semaTryCount = 0uL;
371
372 if (cy_device->flashRwwRequired != 0U)
373 {
374 /* Check for active core is CM0+, or CM4 on single core device */
375 #if (CY_CPU_CORTEX_M0P)
376 bool isPeerCoreEnabled = (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status());
377 #else
378 bool isPeerCoreEnabled = false;
379
380 if (SFLASH_SINGLE_CORE == 0U)
381 {
382 isPeerCoreEnabled = true;
383 }
384 #endif
385
386 if (!isPeerCoreEnabled)
387 {
388 result = CY_FLASH_DRV_SUCCESS;
389 }
390 else
391 {
392 if (IS_CY_PIPE_FREE())
393 {
394 if (CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA))
395 {
396 if (CY_IPC_PIPE_SUCCESS == NOTIFY_PEER_CORE(ipcWaitMessage))
397 {
398 /* Wait for SEMA lock by peer core */
399 while ((CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) && ((semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES)))
400 {
401 /* check for timeout (as maximum tries count) */
402 ++semaTryCount;
403 }
404
405 if (semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES)
406 {
407 result = CY_FLASH_DRV_SUCCESS;
408 }
409 }
410 }
411 }
412 }
413
414 if (CY_FLASH_DRV_SUCCESS == result)
415 {
416 /* Notifier is ready, start of the operation */
417 intr = Cy_SysLib_EnterCriticalSection();
418
419 if (0UL != _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1))
420 {
421 /* Tries to acquire the IPC structure and pass the arguments to SROM API */
422 if (Cy_IPC_Drv_SendMsgPtr(locIpcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
423 {
424 Cy_Flash_RAMDelay(microseconds);
425
426 if (mode == CY_FLASH_NON_BLOCKING_MODE)
427 {
428 /* The Flash operation is successfully initiated */
429 result = CY_FLASH_DRV_OPERATION_STARTED;
430 }
431 else
432 {
433 while (0U != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, *ipcLockStatus))
434 {
435 /* Polls whether the IPC is released and the Flash operation is performed */
436 }
437 result = Cy_Flash_OperationStatus();
438 }
439 }
440 else
441 {
442 /* The IPC structure is already locked by another process */
443 result = CY_FLASH_DRV_IPC_BUSY;
444 }
445 }
446 else
447 {
448 /* SysClk measurement counter is busy */
449 result = CY_FLASH_DRV_IPC_BUSY;
450 }
451
452 if (isPeerCoreEnabled)
453 {
454 while (CY_IPC_SEMA_SUCCESS != Cy_IPC_Sema_Clear(CY_FLASH_WAIT_SEMA, true))
455 {
456 /* Clear SEMA lock */
457 }
458 }
459
460 Cy_SysLib_ExitCriticalSection(intr);
461 /* End of the flash operation */
462 }
463 }
464 else
465 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
466 {
467 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
468 intr = Cy_SysLib_EnterCriticalSection();
469 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
470 /* Tries to acquire the IPC structure and pass the arguments to SROM API */
471 if (Cy_IPC_Drv_SendMsgPtr(locIpcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
472 {
473 if (mode == CY_FLASH_NON_BLOCKING_MODE)
474 {
475 /* The Flash operation is successfully initiated */
476 result = CY_FLASH_DRV_OPERATION_STARTED;
477 }
478 else
479 {
480 while (0U != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, *ipcLockStatus))
481 {
482 /* Polls whether the IPC is released and the Flash operation is performed */
483 }
484
485 result = Cy_Flash_OperationStatus();
486 }
487 }
488 else
489 {
490 /* The IPC structure is already locked by another process */
491 result = CY_FLASH_DRV_IPC_BUSY;
492 }
493 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
494 Cy_SysLib_ExitCriticalSection(intr);
495 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
496 }
497
498 return (result);
499 }
500 CY_SECTION_RAMFUNC_END
501
502
503 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
504 /*******************************************************************************
505 * Function Name: Cy_Flash_RAMDelay
506 ****************************************************************************//**
507 *
508 * Wait for a defined time in the SRAM memory region.
509 *
510 *******************************************************************************/
511 CY_SECTION_RAMFUNC_BEGIN
512 #if !defined (__ICCARM__)
513 CY_NOINLINE
514 #endif
Cy_Flash_RAMDelay(uint32_t microseconds)515 static void Cy_Flash_RAMDelay(uint32_t microseconds)
516 {
517 uint32_t ticks = (microseconds & 0xFFFFUL) * CY_FLASH_TICKS_FOR_1US;
518 if (ticks != CY_FLASH_NO_DELAY)
519 {
520 /* Acquire the IPC to prevent changing of the shared resources at the same time */
521 while(0U == _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_ACQUIRE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT))))
522 {
523 /* Wait until the IPC structure is released by another process */
524 }
525
526 SRSS_TST_DDFT_FAST_CTL_REG = SRSS_TST_DDFT_FAST_CTL_MASK;
527 SRSS_TST_DDFT_SLOW_CTL_REG = SRSS_TST_DDFT_SLOW_CTL_MASK;
528
529 SRSS_CLK_OUTPUT_SLOW = _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0, CY_SYSCLK_MEAS_CLK_IMO) |
530 _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1, CY_FLASH_CLK_OUTPUT_DISABLED);
531
532 /* Load the down-counter without status bit value */
533 SRSS_CLK_CAL_CNT1 = _VAL2FLD(SRSS_CLK_CAL_CNT1_CAL_COUNTER1, ticks);
534
535 /* Make sure that the counter is started */
536 ticks = _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1);
537
538 /* Release the IPC */
539 REG_IPC_STRUCT_RELEASE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0U;
540
541 while (0UL == _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1))
542 {
543 /* Wait until the counter stops counting */
544 }
545 }
546 }
547 CY_SECTION_RAMFUNC_END
548
549 #if (CY_CPU_CORTEX_M4)
550
551 /* Based on bookmark codes of mxs40srompsoc BROS,002-03298 */
552 #define CY_FLASH_PROGRAM_ROW_BOOKMARK (0x00000001UL)
553 #define CY_FLASH_ERASE_ROW_BOOKMARK (0x00000002UL)
554 #define CY_FLASH_WRITE_ROW_ERASE_BOOKMARK (0x00000003UL)
555 #define CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK (0x00000004UL)
556
557 /* Number of the CM0P ticks for function delay corrective time at final stage */
558 #define CY_FLASH_FINAL_STAGE_DELAY_TICKS (1000UL)
559 #define CY_FLASH_FINAL_STAGE_DELAY (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_FINAL_STAGE_DELAY_TICKS))
560
561
562 /*******************************************************************************
563 * Function Name: Cy_Flash_ResumeIrqHandler
564 ****************************************************************************//**
565 *
566 * This is the interrupt service routine to make additional processing of the
567 * flash operations resume phase.
568 *
569 *******************************************************************************/
570 CY_SECTION_RAMFUNC_BEGIN
571 #if !defined (__ICCARM__)
572 CY_NOINLINE
573 #endif
Cy_Flash_ResumeIrqHandler(void)574 void Cy_Flash_ResumeIrqHandler(void)
575 {
576 IPC_STRUCT_Type * locIpcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0);
577
578 uint32_t bookmark;
579 #if ((CY_CPU_CORTEX_M4) && (defined (CY_DEVICE_SECURE)))
580 bookmark = CY_PRA_REG32_GET(CY_PRA_INDX_FLASHC_FM_CTL_BOOKMARK) & 0xffffUL;
581 #else
582 bookmark = FLASHC_FM_CTL_BOOKMARK & 0xffffUL;
583 #endif /* ((CY_CPU_CORTEX_M4) && (defined (CY_DEVICE_SECURE))) */
584
585 uint32_t intr = Cy_SysLib_EnterCriticalSection();
586
587 uint32_t cm0s = CPUSS_CM0_STATUS;
588 bool sflashSingleCore = (0U == SFLASH_SINGLE_CORE);
589
590 if ((bookmark == CY_FLASH_PROGRAM_ROW_BOOKMARK) || (bookmark == CY_FLASH_ERASE_ROW_BOOKMARK) ||
591 (bookmark == CY_FLASH_WRITE_ROW_ERASE_BOOKMARK) || (bookmark == CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK))
592 {
593 if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && sflashSingleCore)
594 {
595 REG_IPC_STRUCT_NOTIFY(locIpcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0));
596 while (CPUSS_CM0_STATUS == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk))
597 {
598 /* Wait until the core is active */
599 }
600 }
601 Cy_Flash_RAMDelay(CY_FLASH_FINAL_STAGE_DELAY);
602 }
603
604 Cy_SysLib_ExitCriticalSection(intr);
605 }
606 CY_SECTION_RAMFUNC_END
607 #endif /* (CY_CPU_CORTEX_M4) */
608 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
609
610
611 /*******************************************************************************
612 * Function Name: Cy_Flash_EraseRow
613 ****************************************************************************//**
614 *
615 * This function erases a single row of flash. Reports success or
616 * a reason for failure. Does not return until the Write operation is
617 * complete. Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in
618 * the case when another process is writing to flash or erasing the row.
619 * User firmware should not enter the Hibernate or Deep Sleep mode until flash Erase
620 * is complete. The Flash operation is allowed in Sleep mode.
621 * During the Flash operation, the device should not be reset, including the
622 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
623 * detect circuits should be configured to generate an interrupt instead of a
624 * reset. Otherwise, portions of flash may undergo unexpected changes.
625 *
626 *******************************************************************************/
Cy_Flash_EraseRow(uint32_t rowAddr)627 cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr)
628 {
629 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
630
631 /* Prepares arguments to be passed to SROM API */
632 if (Cy_Flash_BoundsCheck(rowAddr) != false)
633 {
634 SystemCoreClockUpdate();
635
636 flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW | CY_FLASH_BLOCKING_MODE;
637 flashContext.arg1 = rowAddr;
638 flashContext.arg2 = 0UL;
639 flashContext.arg3 = 0UL;
640
641 if (cy_device->flashEraseDelay != 0U)
642 {
643 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
644 }
645 else
646 {
647 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
648 }
649 }
650
651 return (result);
652 }
653
654
655 /*******************************************************************************
656 * Function Name: Cy_Flash_StartEraseRow
657 ****************************************************************************//**
658 *
659 * Starts erasing a single row of flash. Returns immediately
660 * and reports a successful start or reason for failure.
661 * Reports a CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
662 * by another process. User firmware should not enter the Hibernate or Deep Sleep mode until
663 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
664 * During the flash operation, the device should not be reset, including the
665 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
666 * detect circuits should be configured to generate an interrupt instead of a reset.
667 * Otherwise, portions of flash may undergo unexpected changes.
668 * To avoid situation of reading data from cache memory - before
669 * reading data from previously programmed/erased flash rows, the user must
670 * clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
671 * function.
672 *
673 *******************************************************************************/
Cy_Flash_StartEraseRow(uint32_t rowAddr)674 cy_en_flashdrv_status_t Cy_Flash_StartEraseRow(uint32_t rowAddr)
675 {
676 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
677
678 if (Cy_Flash_BoundsCheck(rowAddr) != false)
679 {
680 SystemCoreClockUpdate();
681
682 /* Prepares arguments to be passed to SROM API */
683 flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW;
684 if (SFLASH_SINGLE_CORE != 0U)
685 {
686 flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
687 }
688
689 flashContext.arg1 = rowAddr;
690 flashContext.arg2 = 0UL;
691 flashContext.arg3 = 0UL;
692
693 if (cy_device->flashEraseDelay != 0U)
694 {
695 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
696 }
697 else
698 {
699 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
700 }
701 }
702
703 return (result);
704 }
705
706
707 /*******************************************************************************
708 * Function Name: Cy_Flash_EraseSector
709 ****************************************************************************//**
710 *
711 * This function erases a sector of flash. Reports success or
712 * a reason for failure. Does not return until the Erase operation is
713 * complete. Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in
714 * the case when another process is writing to flash or erasing the row.
715 * User firmware should not enter the Hibernate or Deep Sleep mode until flash Erase
716 * is complete. The Flash operation is allowed in Sleep mode.
717 * During the Flash operation, the device should not be reset, including the
718 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
719 * detect circuits should be configured to generate an interrupt instead of a
720 * reset. Otherwise, portions of flash may undergo unexpected changes.
721 *
722 *******************************************************************************/
Cy_Flash_EraseSector(uint32_t sectorAddr)723 cy_en_flashdrv_status_t Cy_Flash_EraseSector(uint32_t sectorAddr)
724 {
725 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
726
727 /* Prepares arguments to be passed to SROM API */
728 if (Cy_Flash_BoundsCheck(sectorAddr) != false)
729 {
730 SystemCoreClockUpdate();
731
732 flashContext.opcode = CY_FLASH_OPCODE_ERASE_SECTOR | CY_FLASH_BLOCKING_MODE;
733 flashContext.arg1 = sectorAddr;
734 flashContext.arg2 = 0UL;
735 flashContext.arg3 = 0UL;
736
737 if (cy_device->flashEraseDelay != 0U)
738 {
739 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
740 }
741 else
742 {
743 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
744 }
745 }
746
747 return (result);
748 }
749
750
751 /*******************************************************************************
752 * Function Name: Cy_Flash_StartEraseSector
753 ****************************************************************************//**
754 *
755 * Starts erasing a sector of flash. Returns immediately
756 * and reports a successful start or reason for failure.
757 * Reports a CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
758 * by another process. User firmware should not enter the Hibernate or Deep Sleep mode until
759 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
760 * During the flash operation, the device should not be reset, including the
761 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
762 * detect circuits should be configured to generate an interrupt instead of a reset.
763 * Otherwise, portions of flash may undergo unexpected changes.
764 * Before reading data from previously programmed/erased flash rows, the
765 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
766 * function.
767 *
768 *
769 *******************************************************************************/
Cy_Flash_StartEraseSector(uint32_t sectorAddr)770 cy_en_flashdrv_status_t Cy_Flash_StartEraseSector(uint32_t sectorAddr)
771 {
772 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
773
774 if (Cy_Flash_BoundsCheck(sectorAddr) != false)
775 {
776 SystemCoreClockUpdate();
777
778 /* Prepares arguments to be passed to SROM API */
779 flashContext.opcode = CY_FLASH_OPCODE_ERASE_SECTOR;
780 if (SFLASH_SINGLE_CORE != 0U)
781 {
782 flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
783 }
784
785 flashContext.arg1 = sectorAddr;
786 flashContext.arg2 = 0UL;
787 flashContext.arg3 = 0UL;
788
789 if (cy_device->flashEraseDelay != 0U)
790 {
791 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
792 }
793 else
794 {
795 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
796 }
797 }
798
799 return (result);
800 }
801
802
803 /*******************************************************************************
804 * Function Name: Cy_Flash_EraseSubsector
805 ****************************************************************************//**
806 *
807 * This function erases an 8-row subsector of flash. Reports success or
808 * a reason for failure. Does not return until the Write operation is
809 * complete. Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in
810 * the case when another process is writing to flash or erasing the row.
811 * User firmware should not enter the Hibernate or Deep-Sleep mode until flash Erase
812 * is complete. The Flash operation is allowed in Sleep mode.
813 * During the Flash operation, the device should not be reset, including the
814 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
815 * detect circuits should be configured to generate an interrupt instead of a
816 * reset. Otherwise, portions of flash may undergo unexpected changes.
817 *******************************************************************************/
Cy_Flash_EraseSubsector(uint32_t subSectorAddr)818 cy_en_flashdrv_status_t Cy_Flash_EraseSubsector(uint32_t subSectorAddr)
819 {
820 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
821
822 /* Prepares arguments to be passed to SROM API */
823 if (Cy_Flash_BoundsCheck(subSectorAddr) != false)
824 {
825 SystemCoreClockUpdate();
826
827 flashContext.opcode = CY_FLASH_OPCODE_ERASE_SUB_SECTOR | CY_FLASH_BLOCKING_MODE;
828 flashContext.arg1 = subSectorAddr;
829 flashContext.arg2 = 0UL;
830 flashContext.arg3 = 0UL;
831
832 if (cy_device->flashEraseDelay != 0U)
833 {
834 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
835 }
836 else
837 {
838 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
839 }
840 }
841
842 return (result);
843 }
844
845
846 /*******************************************************************************
847 * Function Name: Cy_Flash_StartEraseSubsector
848 ****************************************************************************//**
849 *
850 * Starts erasing an 8-row subsector of flash. Returns immediately
851 * and reports a successful start or reason for failure.
852 * Reports a CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
853 * by another process. User firmware should not enter the Hibernate or Deep-Sleep mode until
854 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
855 * During the flash operation, the device should not be reset, including the
856 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
857 * detect circuits should be configured to generate an interrupt instead of a reset.
858 * Otherwise, portions of flash may undergo unexpected changes.
859 * Before reading data from previously programmed/erased flash rows, the
860 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
861 * function.
862 *******************************************************************************/
Cy_Flash_StartEraseSubsector(uint32_t subSectorAddr)863 cy_en_flashdrv_status_t Cy_Flash_StartEraseSubsector(uint32_t subSectorAddr)
864 {
865 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
866
867 if (Cy_Flash_BoundsCheck(subSectorAddr) != false)
868 {
869 SystemCoreClockUpdate();
870
871 /* Prepares arguments to be passed to SROM API */
872 flashContext.opcode = CY_FLASH_OPCODE_ERASE_SUB_SECTOR;
873 if (SFLASH_SINGLE_CORE != 0U)
874 {
875 flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
876 }
877
878 flashContext.arg1 = subSectorAddr;
879 flashContext.arg2 = 0UL;
880 flashContext.arg3 = 0UL;
881
882 if (cy_device->flashEraseDelay != 0U)
883 {
884 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
885 }
886 else
887 {
888 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
889 }
890 }
891
892 return (result);
893 }
894
895
896 /*******************************************************************************
897 * Function Name: Cy_Flash_ProgramRow
898 ****************************************************************************//**
899 *
900 * This function writes an array of data to a single row of flash. Reports
901 * success or a reason for failure. Does not return until the Program operation
902 * is complete.
903 * Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case
904 * when another process is writing to flash. User firmware should not enter the
905 * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation
906 * is allowed in Sleep mode. During the Flash operation, the device should not be
907 * reset, including the XRES pin, a software reset, and watchdog reset sources.
908 * Also, low-voltage detect circuits should be configured to generate an interrupt
909 * instead of a reset. Otherwise, portions of flash may undergo unexpected
910 * changes.\n
911 * Before calling this function, the target flash region must be erased by
912 * the StartErase/EraseRow function.\n
913 * Data to be programmed must be located in the SRAM memory region.
914 * Before reading data from previously programmed/erased flash rows, the
915 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
916 * function.
917 *
918 *******************************************************************************/
Cy_Flash_ProgramRow(uint32_t rowAddr,const uint32_t * data)919 cy_en_flashdrv_status_t Cy_Flash_ProgramRow(uint32_t rowAddr, const uint32_t* data)
920 {
921 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
922
923 /* Checks whether the input parameters are valid */
924 if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
925 {
926 SystemCoreClockUpdate();
927
928 /* Prepares arguments to be passed to SROM API */
929 flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_BLOCKING_MODE;
930 flashContext.arg1 = CY_FLASH_DATA_LOC_SRAM;
931 flashContext.arg2 = rowAddr;
932 flashContext.arg3 = (uint32_t)data;
933
934 if (cy_device->flashProgramDelay != 0U)
935 {
936 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY);
937 }
938 else
939 {
940 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
941 }
942 }
943
944 return (result);
945 }
946
947
948 /*******************************************************************************
949 * Function Name: Cy_Flash_WriteRow
950 ****************************************************************************//**
951 *
952 * This function writes an array of data to a single row of flash. This is done
953 * in three steps - pre-program, erase and then program flash row with the input
954 * data. Reports success or a reason for failure. Does not return until the Write
955 * operation is complete.
956 * Returns immediately and reports a CY_FLASH_DRV_IPC_BUSY error in the case
957 * when another process is writing to flash. User firmware should not enter the
958 * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation
959 * is allowed in Sleep mode. During the Flash operation, the
960 * device should not be reset, including the XRES pin, a software
961 * reset, and watchdog reset sources. Also, low-voltage detect
962 * circuits should be configured to generate an interrupt
963 * instead of a reset. Otherwise, portions of flash may undergo
964 * unexpected changes.
965 *
966 *******************************************************************************/
Cy_Flash_WriteRow(uint32_t rowAddr,const uint32_t * data)967 cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data)
968 {
969 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
970
971 /* Checks whether the input parameters are valid */
972 if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
973 {
974 SystemCoreClockUpdate();
975
976 /* Prepares arguments to be passed to SROM API */
977 flashContext.opcode = CY_FLASH_OPCODE_WRITE_ROW | CY_FLASH_BLOCKING_MODE;
978 flashContext.arg1 = 0UL;
979 flashContext.arg2 = rowAddr;
980 flashContext.arg3 = (uint32_t)data;
981
982 if (cy_device->flashWriteDelay != 0U)
983 {
984 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_WRITE_DELAY);
985 }
986 else
987 {
988 result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
989 }
990 }
991
992 return (result);
993 }
994
995
996 /*******************************************************************************
997 * Function Name: Cy_Flash_StartWrite
998 ****************************************************************************//**
999 *
1000 * Performs pre-program, erase and then starts programming the flash row with
1001 * the input data. Returns immediately and reports a successful start
1002 * or reason for failure. Reports a CY_FLASH_DRV_IPC_BUSY error
1003 * in the case when another process is writing to flash. User
1004 * firmware should not enter the Hibernate or Deep-Sleep mode until
1005 * flash Write is complete. The Flash operation is allowed in Sleep mode.
1006 * During the flash operation, the device should not be reset, including the
1007 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
1008 * detect circuits should be configured to generate an interrupt instead of a reset.
1009 * Otherwise, portions of flash may undergo unexpected changes.
1010 * Before reading data from previously programmed/erased flash rows, the
1011 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
1012 * function.
1013 *
1014 *******************************************************************************/
Cy_Flash_StartWrite(uint32_t rowAddr,const uint32_t * data)1015 cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data)
1016 {
1017 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1018
1019 /* Checks whether the input parameters are valid */
1020 if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1021 {
1022 result = Cy_Flash_StartEraseRow(rowAddr);
1023
1024 if (CY_FLASH_DRV_OPERATION_STARTED == result)
1025 {
1026 /* Polls whether the IPC is released and the Flash operation is performed */
1027 do
1028 {
1029 result = Cy_Flash_OperationStatus();
1030 }
1031 while (result == CY_FLASH_DRV_OPCODE_BUSY);
1032
1033 if (CY_FLASH_DRV_SUCCESS == result)
1034 {
1035 result = Cy_Flash_StartProgram(rowAddr, data);
1036 }
1037 }
1038 }
1039
1040 return (result);
1041 }
1042
1043
1044 /*******************************************************************************
1045 * Function Name: Cy_Flash_IsOperationComplete
1046 ****************************************************************************//**
1047 *
1048 * Reports a successful operation result, reason of failure or busy status
1049 * ( CY_FLASH_DRV_OPCODE_BUSY ).
1050 *******************************************************************************/
Cy_Flash_IsOperationComplete(void)1051 cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void)
1052 {
1053 return (Cy_Flash_OperationStatus());
1054 }
1055
1056
1057 /*******************************************************************************
1058 * Function Name: Cy_Flash_StartProgram
1059 ****************************************************************************//**
1060 *
1061 * Starts writing an array of data to a single row of flash. Returns immediately
1062 * and reports a successful start or reason for failure.
1063 * Reports a CY_FLASH_DRV_IPC_BUSY error if another process is writing
1064 * to flash. The user firmware should not enter Hibernate or Deep-Sleep mode until flash
1065 * Program is complete. The Flash operation is allowed in Sleep mode.
1066 * During the Flash operation, the device should not be reset, including the
1067 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
1068 * detect circuits should be configured to generate an interrupt instead of a reset.
1069 * Otherwise, portions of flash may undergo unexpected changes.\n
1070 * Before calling this function, the target flash region must be erased by
1071 * the StartEraseRow/EraseRow function.\n
1072 * Data to be programmed must be located in the SRAM memory region.
1073 * Before reading data from previously programmed/erased flash rows, the
1074 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
1075 * function.
1076 *******************************************************************************/
Cy_Flash_StartProgram(uint32_t rowAddr,const uint32_t * data)1077 cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data)
1078 {
1079 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1080
1081 if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1082 {
1083 SystemCoreClockUpdate();
1084
1085 /* Prepares arguments to be passed to SROM API */
1086 flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW;
1087
1088 if (SFLASH_SINGLE_CORE != 0U)
1089 {
1090 flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
1091 }
1092
1093 flashContext.arg1 = CY_FLASH_DATA_LOC_SRAM;
1094 flashContext.arg2 = rowAddr;
1095 flashContext.arg3 = (uint32_t)data;
1096
1097 if (cy_device->flashProgramDelay != 0U)
1098 {
1099 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY);
1100 }
1101 else
1102 {
1103 result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
1104 }
1105 }
1106
1107 return (result);
1108 }
1109
1110
1111 /*******************************************************************************
1112 * Function Name: Cy_Flash_RowChecksum
1113 ****************************************************************************//**
1114 *
1115 * Returns a checksum value of the specified flash row.
1116 *
1117 *******************************************************************************/
Cy_Flash_RowChecksum(uint32_t rowAddr,uint32_t * checksumPtr)1118 cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowAddr, uint32_t* checksumPtr)
1119 {
1120 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1121 uint32_t resTmp;
1122 uint32_t rowID;
1123
1124 /* Checks whether the input parameters are valid */
1125 if ((Cy_Flash_BoundsCheck(rowAddr)) && (NULL != checksumPtr))
1126 {
1127 rowID = Cy_Flash_GetRowNum(rowAddr);
1128
1129 /* Prepares arguments to be passed to SROM API */
1130 flashContext.opcode = CY_FLASH_OPCODE_CHECKSUM |
1131 (((rowID >> CY_FLASH_REGION_ID_SHIFT) & CY_FLASH_REGION_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT) |
1132 ((rowID & CY_FLASH_ROW_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT);
1133
1134 /* Tries to acquire the IPC structure and pass the arguments to SROM API */
1135 if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0,
1136 (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
1137 {
1138 /* Polls whether IPC is released and the Flash operation is performed */
1139 while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false)
1140 {
1141 /* Wait till IPC is released */
1142 }
1143
1144 resTmp = flashContext.opcode >> CY_FLASH_ERROR_SHIFT;
1145
1146 if (resTmp == CY_FLASH_ERROR_NO_ERROR)
1147 {
1148 result = CY_FLASH_DRV_SUCCESS;
1149
1150 if (CY_IPC_V1)
1151 {
1152 *checksumPtr = flashContext.opcode & CY_FLASH_RESULT_MASK;
1153 }
1154 else
1155 {
1156 *checksumPtr = REG_IPC_STRUCT_DATA1(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL));
1157 }
1158 }
1159 else
1160 {
1161 result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1162 }
1163
1164 }
1165 else
1166 {
1167 /* The IPC structure is already locked by another process */
1168 result = CY_FLASH_DRV_IPC_BUSY;
1169 }
1170 }
1171
1172 return (result);
1173 }
1174
1175
1176 /*******************************************************************************
1177 * Function Name: Cy_Flash_CalculateHash
1178 ****************************************************************************//**
1179 *
1180 * Returns a hash value of the specified region of flash.
1181 *******************************************************************************/
Cy_Flash_CalculateHash(const uint32_t * data,uint32_t numberOfBytes,uint32_t * hashPtr)1182 cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32_t numberOfBytes, uint32_t* hashPtr)
1183 {
1184 cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1185 volatile uint32_t resTmp;
1186
1187 /* Checks whether the input parameters are valid */
1188 if ((data != NULL) && (0UL != numberOfBytes))
1189 {
1190 /* Prepares arguments to be passed to SROM API */
1191 flashContext.opcode = CY_FLASH_OPCODE_HASH;
1192 flashContext.arg1 = (uint32_t)data;
1193 flashContext.arg2 = numberOfBytes;
1194
1195 /* Tries to acquire the IPC structure and pass the arguments to SROM API */
1196 if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0,
1197 (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
1198 {
1199 /* Polls whether IPC is released and the Flash operation is performed */
1200 while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false)
1201 {
1202 /* Wait till IPC is released */
1203 }
1204
1205 resTmp = flashContext.opcode;
1206
1207 if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR)
1208 {
1209 result = CY_FLASH_DRV_SUCCESS;
1210 *hashPtr = flashContext.opcode & CY_FLASH_RESULT_MASK;
1211 }
1212 else
1213 {
1214 result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1215 }
1216 }
1217 else
1218 {
1219 /* The IPC structure is already locked by another process */
1220 result = CY_FLASH_DRV_IPC_BUSY;
1221 }
1222 }
1223
1224 return (result);
1225 }
1226
1227
1228 /*******************************************************************************
1229 * Function Name: Cy_Flash_GetRowNum
1230 ****************************************************************************//**
1231 *
1232 * Returns flash region ID and row number of the Flash address.
1233 *******************************************************************************/
Cy_Flash_GetRowNum(uint32_t flashAddr)1234 static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr)
1235 {
1236 uint32_t result;
1237
1238 #if (CY_EM_EEPROM_SIZE>0)
1239 if ((flashAddr >= CY_EM_EEPROM_BASE) && (flashAddr < (CY_EM_EEPROM_BASE + CY_EM_EEPROM_SIZE)))
1240 {
1241 result = (CY_FLASH_REGION_ID_EM_EEPROM << CY_FLASH_REGION_ID_SHIFT) |
1242 ((flashAddr - CY_EM_EEPROM_BASE) / CY_FLASH_SIZEOF_ROW);
1243 }
1244 else
1245 #endif
1246 if ((flashAddr >= SFLASH_BASE) && (flashAddr < (SFLASH_BASE + SFLASH_SECTION_SIZE)))
1247 {
1248 result = (CY_FLASH_REGION_ID_SFLASH << CY_FLASH_REGION_ID_SHIFT) |
1249 ((flashAddr - SFLASH_BASE) / CY_FLASH_SIZEOF_ROW);
1250 }
1251 else
1252 {
1253 result = (CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) |
1254 ((flashAddr - CY_FLASH_BASE) / CY_FLASH_SIZEOF_ROW);
1255 }
1256
1257 return (result);
1258 }
1259
1260
1261 /*******************************************************************************
1262 * Function Name: Cy_Flash_BoundsCheck
1263 ****************************************************************************//**
1264 *
1265 * The function checks the following conditions:
1266 * - if Flash address is equal to start address of the row
1267 *******************************************************************************/
Cy_Flash_BoundsCheck(uint32_t flashAddr)1268 static bool Cy_Flash_BoundsCheck(uint32_t flashAddr)
1269 {
1270 return ((flashAddr % CY_FLASH_SIZEOF_ROW) == 0UL);
1271 }
1272
1273
1274 /*******************************************************************************
1275 * Function Name: Cy_Flash_ProcessOpcode
1276 ****************************************************************************//**
1277 *
1278 * Converts System Call returns to the Flash driver return defines.
1279 *******************************************************************************/
Cy_Flash_ProcessOpcode(uint32_t opcode)1280 static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode)
1281 {
1282 cy_en_flashdrv_status_t result;
1283
1284 switch (opcode)
1285 {
1286 case 0UL:
1287 {
1288 result = CY_FLASH_DRV_SUCCESS;
1289 break;
1290 }
1291 case CY_FLASH_ROMCODE_SUCCESS:
1292 {
1293 result = CY_FLASH_DRV_SUCCESS;
1294 break;
1295 }
1296 case CY_FLASH_ROMCODE_INVALID_PROTECTION:
1297 {
1298 result = CY_FLASH_DRV_INV_PROT;
1299 break;
1300 }
1301 case CY_FLASH_ROMCODE_INVALID_FM_PL:
1302 {
1303 result = CY_FLASH_DRV_INVALID_FM_PL;
1304 break;
1305 }
1306 case CY_FLASH_ROMCODE_INVALID_FLASH_ADDR:
1307 {
1308 result = CY_FLASH_DRV_INVALID_FLASH_ADDR;
1309 break;
1310 }
1311 case CY_FLASH_ROMCODE_ROW_PROTECTED:
1312 {
1313 result = CY_FLASH_DRV_ROW_PROTECTED;
1314 break;
1315 }
1316 case CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR:
1317 {
1318 result = CY_FLASH_DRV_PROGRESS_NO_ERROR;
1319 break;
1320 }
1321 case (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
1322 {
1323 result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1324 break;
1325 }
1326 case CY_FLASH_IS_OPERATION_STARTED :
1327 {
1328 result = CY_FLASH_DRV_OPERATION_STARTED;
1329 break;
1330 }
1331 case CY_FLASH_IS_BUSY :
1332 {
1333 result = CY_FLASH_DRV_OPCODE_BUSY;
1334 break;
1335 }
1336 case CY_FLASH_IS_IPC_BUSY :
1337 {
1338 result = CY_FLASH_DRV_IPC_BUSY;
1339 break;
1340 }
1341 case CY_FLASH_IS_INVALID_INPUT_PARAMETERS :
1342 {
1343 result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1344 break;
1345 }
1346 default:
1347 {
1348 result = CY_FLASH_DRV_ERR_UNC;
1349 break;
1350 }
1351 }
1352
1353 return (result);
1354 }
1355
1356
1357 /*******************************************************************************
1358 * Function Name: Cy_Flash_OperationStatus
1359 ****************************************************************************//**
1360 *
1361 * Checks the status of the Flash Operation, and returns it.
1362 *******************************************************************************/
Cy_Flash_OperationStatus(void)1363 static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void)
1364 {
1365 cy_en_flashdrv_status_t result = CY_FLASH_DRV_OPCODE_BUSY;
1366
1367 /* Checks if the IPC structure is not locked */
1368 if (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) == false)
1369 {
1370 /* The result of SROM API calling is returned to the driver context */
1371 result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1372
1373 /* Clear pre-fetch cache after flash operation */
1374 #if CY_CPU_CORTEX_M4 && defined (CY_DEVICE_SECURE)
1375 CY_PRA_REG32_SET(CY_PRA_INDX_FLASHC_FLASH_CMD, FLASHC_FLASH_CMD_INV_Msk);
1376 while (CY_PRA_REG32_GET(CY_PRA_INDX_FLASHC_FLASH_CMD) != 0U)
1377 {
1378 }
1379 #else
1380 FLASHC_FLASH_CMD = FLASHC_FLASH_CMD_INV_Msk;
1381 while (FLASHC_FLASH_CMD != 0U)
1382 {
1383 }
1384 #endif /* CY_CPU_CORTEX_M4 && defined (CY_DEVICE_SECURE) */
1385 }
1386
1387 return (result);
1388 }
1389
1390
1391 /*******************************************************************************
1392 * Function Name: Cy_Flash_GetExternalStatus
1393 ****************************************************************************//**
1394 *
1395 * This function handles the case where a module such as security image captures
1396 * a system call from this driver and reports its own status or error code,
1397 * for example protection violation. In that case, a function from this
1398 * driver returns an unknown error (see cy_en_flashdrv_status_t). After receipt
1399 * of an unknown error, the user may call this function to get the status
1400 * of the capturing module.
1401 *
1402 * The user is responsible for parsing the content of the returned value
1403 * and casting it to the appropriate enumeration.
1404 *******************************************************************************/
Cy_Flash_GetExternalStatus(void)1405 uint32_t Cy_Flash_GetExternalStatus(void)
1406 {
1407 return (flashContext.opcode);
1408 }
1409
1410 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
1411 #endif /* CY_IP_M4CPUSS */
1412
1413 /* [] END OF FILE */
1414