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 = &REG_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