1 /***************************************************************************//**
2 * \file cy_flash.c
3 * \version 3.50.1
4 *
5 * \brief
6 * Provides the public functions for the API for the PSoC 6 Flash Driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2016-2020 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     * \ref 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 * \snippet flash/snippet/main.c Flash Initialization
337 *
338 *******************************************************************************/
Cy_Flash_Init(void)339 void Cy_Flash_Init(void)
340 {
341     #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
342         CY_SECTION_SHAREDMEM
343         CY_ALIGN(4) static cy_stc_flash_notify_t ipcWaitMessageStc;
344 
345         Cy_Flash_InitExt(&ipcWaitMessageStc);
346     #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
347 }
348 
349 
350 /*******************************************************************************
351 * Function Name: Cy_Flash_SendCmd
352 ****************************************************************************//**
353 *
354 * Sends a command to the SROM via the IPC channel. The function is placed to the
355 * SRAM memory to guarantee successful operation. After an IPC message is sent,
356 * the function waits for a defined time before exiting the function.
357 *
358 * \param mode
359 * Sets the blocking or non-blocking Flash operation.
360 *
361 * \param microseconds
362 * The number of microseconds to wait before exiting the functions
363 * in range 0-65535 us.
364 *
365 * \return Returns the status of the Flash operation,
366 * see \ref cy_en_flashdrv_status_t.
367 *
368 *******************************************************************************/
369 CY_SECTION_RAMFUNC_BEGIN
370 #if !defined (__ICCARM__)
371     CY_NOINLINE
372 #endif
Cy_Flash_SendCmd(uint32_t mode,uint32_t microseconds)373 static cy_en_flashdrv_status_t Cy_Flash_SendCmd(uint32_t mode, uint32_t microseconds)
374 {
375     cy_en_flashdrv_status_t result = CY_FLASH_DRV_IPC_BUSY;
376     IPC_STRUCT_Type * locIpcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL);
377     volatile uint32_t *ipcLockStatus = &REG_IPC_STRUCT_LOCK_STATUS(locIpcBase);
378 
379 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
380     uint32_t intr;
381     uint32_t semaTryCount = 0uL;
382 
383     if (cy_device->flashRwwRequired != 0U)
384     {
385         /* Check for active core is CM0+, or CM4 on single core device */
386     #if (CY_CPU_CORTEX_M0P)
387         bool isPeerCoreEnabled = (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status());
388     #else
389         bool isPeerCoreEnabled = false;
390 
391         if (SFLASH_SINGLE_CORE == 0U)
392         {
393             isPeerCoreEnabled = true;
394         }
395     #endif
396 
397         if (!isPeerCoreEnabled)
398         {
399             result = CY_FLASH_DRV_SUCCESS;
400         }
401         else
402         {
403             if (IS_CY_PIPE_FREE())
404             {
405                 if (CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA))
406                 {
407                     if (CY_IPC_PIPE_SUCCESS == NOTIFY_PEER_CORE(ipcWaitMessage))
408                     {
409                         /* Wait for SEMA lock by peer core */
410                         while ((CY_IPC_SEMA_STATUS_LOCKED != Cy_IPC_Sema_Status(CY_FLASH_WAIT_SEMA)) && ((semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES)))
411                         {
412                             /* check for timeout (as maximum tries count) */
413                             ++semaTryCount;
414                         }
415 
416                         if (semaTryCount < CY_FLASH_SEMA_WAIT_MAX_TRIES)
417                         {
418                             result = CY_FLASH_DRV_SUCCESS;
419                         }
420                     }
421                 }
422             }
423         }
424 
425         if (CY_FLASH_DRV_SUCCESS == result)
426         {
427             /* Notifier is ready, start of the operation */
428             intr = Cy_SysLib_EnterCriticalSection();
429 
430             if (0UL != _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1))
431             {
432                /* Tries to acquire the IPC structure and pass the arguments to SROM API */
433                 if (Cy_IPC_Drv_SendMsgPtr(locIpcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
434                 {
435                     Cy_Flash_RAMDelay(microseconds);
436 
437                     if (mode == CY_FLASH_NON_BLOCKING_MODE)
438                     {
439                         /* The Flash operation is successfully initiated */
440                         result = CY_FLASH_DRV_OPERATION_STARTED;
441                     }
442                     else
443                     {
444                         while (0U != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, *ipcLockStatus))
445                         {
446                             /* Polls whether the IPC is released and the Flash operation is performed */
447                         }
448                         result = Cy_Flash_OperationStatus();
449                     }
450                 }
451                 else
452                 {
453                     /* The IPC structure is already locked by another process */
454                     result = CY_FLASH_DRV_IPC_BUSY;
455                 }
456             }
457             else
458             {
459                 /* SysClk measurement counter is busy */
460                 result = CY_FLASH_DRV_IPC_BUSY;
461             }
462 
463             if (isPeerCoreEnabled)
464             {
465                 while (CY_IPC_SEMA_SUCCESS != Cy_IPC_Sema_Clear(CY_FLASH_WAIT_SEMA, true))
466                 {
467                     /* Clear SEMA lock */
468                 }
469             }
470 
471             Cy_SysLib_ExitCriticalSection(intr);
472             /* End of the flash operation */
473         }
474     }
475     else
476 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
477     {
478     #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
479         intr = Cy_SysLib_EnterCriticalSection();
480     #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
481         /* Tries to acquire the IPC structure and pass the arguments to SROM API */
482         if (Cy_IPC_Drv_SendMsgPtr(locIpcBase, CY_FLASH_IPC_NOTIFY_STRUCT0, (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
483         {
484             if (mode == CY_FLASH_NON_BLOCKING_MODE)
485             {
486                 /* The Flash operation is successfully initiated */
487                 result = CY_FLASH_DRV_OPERATION_STARTED;
488             }
489             else
490             {
491                 while (0U != _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, *ipcLockStatus))
492                 {
493                     /* Polls whether the IPC is released and the Flash operation is performed */
494                 }
495 
496                 result = Cy_Flash_OperationStatus();
497             }
498         }
499         else
500         {
501             /* The IPC structure is already locked by another process */
502             result = CY_FLASH_DRV_IPC_BUSY;
503         }
504     #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
505         Cy_SysLib_ExitCriticalSection(intr);
506     #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
507     }
508 
509     return (result);
510 }
511 CY_SECTION_RAMFUNC_END
512 
513 
514 #if !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED)
515     /*******************************************************************************
516     * Function Name: Cy_Flash_RAMDelay
517     ****************************************************************************//**
518     *
519     * Wait for a defined time in the SRAM memory region.
520     *
521     * \param microseconds
522     * Delay time in microseconds in range 0-65535 us.
523     *
524     *******************************************************************************/
525     CY_SECTION_RAMFUNC_BEGIN
526     #if !defined (__ICCARM__)
527         CY_NOINLINE
528     #endif
Cy_Flash_RAMDelay(uint32_t microseconds)529     static void Cy_Flash_RAMDelay(uint32_t microseconds)
530     {
531         uint32_t ticks = (microseconds & 0xFFFFUL) * CY_FLASH_TICKS_FOR_1US;
532         if (ticks != CY_FLASH_NO_DELAY)
533         {
534             /* Acquire the IPC to prevent changing of the shared resources at the same time */
535             while(0U == _FLD2VAL(IPC_STRUCT_ACQUIRE_SUCCESS, REG_IPC_STRUCT_ACQUIRE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT))))
536             {
537                 /* Wait until the IPC structure is released by another process */
538             }
539 
540             SRSS_TST_DDFT_FAST_CTL_REG  = SRSS_TST_DDFT_FAST_CTL_MASK;
541             SRSS_TST_DDFT_SLOW_CTL_REG  = SRSS_TST_DDFT_SLOW_CTL_MASK;
542 
543             SRSS_CLK_OUTPUT_SLOW = _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL0, CY_SYSCLK_MEAS_CLK_IMO) |
544                                    _VAL2FLD(SRSS_CLK_OUTPUT_SLOW_SLOW_SEL1, CY_FLASH_CLK_OUTPUT_DISABLED);
545 
546             /* Load the down-counter without status bit value */
547             SRSS_CLK_CAL_CNT1 = _VAL2FLD(SRSS_CLK_CAL_CNT1_CAL_COUNTER1, ticks);
548 
549             /* Make sure that the counter is started */
550             ticks = _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1);
551 
552             /* Release the IPC */
553             REG_IPC_STRUCT_RELEASE(CY_IPC_STRUCT_PTR(CY_IPC_CHAN_DDFT)) = 0U;
554 
555             while (0UL == _FLD2VAL(SRSS_CLK_CAL_CNT1_CAL_COUNTER_DONE, SRSS_CLK_CAL_CNT1))
556             {
557                 /* Wait until the counter stops counting */
558             }
559         }
560     }
561     CY_SECTION_RAMFUNC_END
562 
563     #if (CY_CPU_CORTEX_M4)
564 
565         /* Based on bookmark codes of mxs40srompsoc BROS,002-03298 */
566         #define CY_FLASH_PROGRAM_ROW_BOOKMARK        (0x00000001UL)
567         #define CY_FLASH_ERASE_ROW_BOOKMARK          (0x00000002UL)
568         #define CY_FLASH_WRITE_ROW_ERASE_BOOKMARK    (0x00000003UL)
569         #define CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK  (0x00000004UL)
570 
571         /* Number of the CM0P ticks for function delay corrective time at final stage */
572         #define CY_FLASH_FINAL_STAGE_DELAY_TICKS     (1000UL)
573         #define CY_FLASH_FINAL_STAGE_DELAY           (130UL + CY_FLASH_DELAY_CORRECTIVE(CY_FLASH_FINAL_STAGE_DELAY_TICKS))
574 
575 
576         /*******************************************************************************
577         * Function Name: Cy_Flash_ResumeIrqHandler
578         ****************************************************************************//**
579         *
580         * This is the interrupt service routine to make additional processing of the
581         * flash operations resume phase.
582         *
583         *******************************************************************************/
584         CY_SECTION_RAMFUNC_BEGIN
585         #if !defined (__ICCARM__)
586             CY_NOINLINE
587         #endif
Cy_Flash_ResumeIrqHandler(void)588         void Cy_Flash_ResumeIrqHandler(void)
589         {
590             IPC_STRUCT_Type * locIpcBase = Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_CYPIPE_EP0);
591 
592             uint32_t bookmark;
593             #if ((CY_CPU_CORTEX_M4) && (defined (CY_DEVICE_SECURE)))
594                 bookmark = CY_PRA_REG32_GET(CY_PRA_INDX_FLASHC_FM_CTL_BOOKMARK) & 0xffffUL;
595             #else
596                 bookmark = FLASHC_FM_CTL_BOOKMARK & 0xffffUL;
597             #endif /* ((CY_CPU_CORTEX_M4) && (defined (CY_DEVICE_SECURE))) */
598 
599             uint32_t intr = Cy_SysLib_EnterCriticalSection();
600 
601             uint32_t cm0s = CPUSS_CM0_STATUS;
602             bool sflashSingleCore = (0U == SFLASH_SINGLE_CORE);
603 
604             if ((bookmark == CY_FLASH_PROGRAM_ROW_BOOKMARK) || (bookmark == CY_FLASH_ERASE_ROW_BOOKMARK) ||
605                 (bookmark == CY_FLASH_WRITE_ROW_ERASE_BOOKMARK) || (bookmark == CY_FLASH_WRITE_ROW_PROGRAM_BOOKMARK))
606             {
607                 if ((cm0s == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk)) && sflashSingleCore)
608                 {
609                     REG_IPC_STRUCT_NOTIFY(locIpcBase) = _VAL2FLD(IPC_STRUCT_NOTIFY_INTR_NOTIFY, (1UL << CY_IPC_INTR_CYPIPE_EP0));
610                     while (CPUSS_CM0_STATUS == (CPUSS_CM0_STATUS_SLEEPING_Msk | CPUSS_CM0_STATUS_SLEEPDEEP_Msk))
611                     {
612                         /* Wait until the core is active */
613                     }
614                 }
615                 Cy_Flash_RAMDelay(CY_FLASH_FINAL_STAGE_DELAY);
616             }
617 
618             Cy_SysLib_ExitCriticalSection(intr);
619         }
620         CY_SECTION_RAMFUNC_END
621     #endif /* (CY_CPU_CORTEX_M4) */
622 #endif /* !defined (CY_FLASH_RWW_DRV_SUPPORT_DISABLED) */
623 
624 
625 /*******************************************************************************
626 * Function Name: Cy_Flash_EraseRow
627 ****************************************************************************//**
628 *
629 * This function erases a single row of flash. Reports success or
630 * a reason for failure. Does not return until the Write operation is
631 * complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in
632 * the case when another process is writing to flash or erasing the row.
633 * User firmware should not enter the Hibernate or Deep Sleep mode until flash Erase
634 * is complete. The Flash operation is allowed in Sleep mode.
635 * During the Flash operation, the device should not be reset, including the
636 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
637 * detect circuits should be configured to generate an interrupt instead of a
638 * reset. Otherwise, portions of flash may undergo unexpected changes.
639 * \note  A Read while Write violation occurs when a flash Read operation is initiated
640 * in the same or neighboring flash sector where the flash Write, Erase, or
641 * Program operation is working. This violation may cause a HardFault exception.
642 * To avoid the Read while Write violation,
643 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
644 *
645 * \param rowAddr Address of the flash row number.
646 * The Read-while-Write violation occurs when the flash read operation is
647 * initiated in the same flash sector where the flash write operation is
648 * performing. Refer to the device datasheet for the details.
649 * Address must match row start address.
650 *
651 * \return Returns the status of the Flash operation,
652 * see \ref cy_en_flashdrv_status_t.
653 *
654 *******************************************************************************/
Cy_Flash_EraseRow(uint32_t rowAddr)655 cy_en_flashdrv_status_t Cy_Flash_EraseRow(uint32_t rowAddr)
656 {
657     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
658 
659     /* Prepares arguments to be passed to SROM API */
660     if (Cy_Flash_BoundsCheck(rowAddr) != false)
661     {
662         SystemCoreClockUpdate();
663 
664         flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW | CY_FLASH_BLOCKING_MODE;
665         flashContext.arg1 = rowAddr;
666         flashContext.arg2 = 0UL;
667         flashContext.arg3 = 0UL;
668 
669         if (cy_device->flashEraseDelay != 0U)
670         {
671             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
672         }
673         else
674         {
675             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
676         }
677     }
678 
679     return (result);
680 }
681 
682 
683 /*******************************************************************************
684 * Function Name: Cy_Flash_StartEraseRow
685 ****************************************************************************//**
686 *
687 * Starts erasing a single row of flash. Returns immediately
688 * and reports a successful start or reason for failure.
689 * Reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
690 * by another process. User firmware should not enter the Hibernate or Deep Sleep mode until
691 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
692 * During the flash operation, the device should not be reset, including the
693 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
694 * detect circuits should be configured to generate an interrupt instead of a reset.
695 * Otherwise, portions of flash may undergo unexpected changes.
696 * \note To avoid situation of reading data from cache memory - before
697 * reading data from previously programmed/erased flash rows, the user must
698 * clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
699 * function.
700 * \note  A Read while Write violation occurs when a flash Read operation is initiated
701 * in the same or neighboring flash sector where the flash Write, Erase, or
702 * Program operation is working. This violation may cause a HardFault exception.
703 * To avoid the Read while Write violation,
704 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
705 *
706 * \param rowAddr Address of the flash row number.
707 * The Read-while-Write violation occurs when the flash read operation is
708 * initiated in the same flash sector where the flash erase operation is
709 * performing. Refer to the device datasheet for the details.
710 * Address must match row start address.
711 *
712 * \return Returns the status of the Flash operation,
713 * see \ref cy_en_flashdrv_status_t.
714 *
715 *******************************************************************************/
Cy_Flash_StartEraseRow(uint32_t rowAddr)716 cy_en_flashdrv_status_t Cy_Flash_StartEraseRow(uint32_t rowAddr)
717 {
718     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
719 
720     if (Cy_Flash_BoundsCheck(rowAddr) != false)
721     {
722         SystemCoreClockUpdate();
723 
724         /* Prepares arguments to be passed to SROM API */
725         flashContext.opcode = CY_FLASH_OPCODE_ERASE_ROW;
726         if (SFLASH_SINGLE_CORE != 0U)
727         {
728             flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
729         }
730 
731         flashContext.arg1 = rowAddr;
732         flashContext.arg2 = 0UL;
733         flashContext.arg3 = 0UL;
734 
735         if (cy_device->flashEraseDelay != 0U)
736         {
737             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
738         }
739         else
740         {
741             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
742         }
743     }
744 
745     return (result);
746 }
747 
748 
749 /*******************************************************************************
750 * Function Name: Cy_Flash_EraseSector
751 ****************************************************************************//**
752 *
753 * This function erases a sector of flash. Reports success or
754 * a reason for failure. Does not return until the Erase operation is
755 * complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in
756 * the case when another process is writing to flash or erasing the row.
757 * User firmware should not enter the Hibernate or Deep Sleep mode until flash Erase
758 * is complete. The Flash operation is allowed in Sleep mode.
759 * During the Flash operation, the device should not be reset, including the
760 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
761 * detect circuits should be configured to generate an interrupt instead of a
762 * reset. Otherwise, portions of flash may undergo unexpected changes.
763 * \note  A Read while Write violation occurs when a flash Read operation is initiated
764 * in the same or neighboring flash sector where the flash Write, Erase, or
765 * Program operation is working. This violation may cause a HardFault exception.
766 * To avoid the Read while Write violation,
767 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
768 *
769 * \param sectorAddr Address of the flash row number.
770 * The Read-while-Write violation occurs when the flash read operation is
771 * initiated in the same flash sector where the flash write operation is
772 * performing. Refer to the device datasheet for the details.
773 * Address must match row start address.
774 *
775 * \return Returns the status of the Flash operation,
776 * see \ref cy_en_flashdrv_status_t.
777 *
778 *******************************************************************************/
Cy_Flash_EraseSector(uint32_t sectorAddr)779 cy_en_flashdrv_status_t Cy_Flash_EraseSector(uint32_t sectorAddr)
780 {
781     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
782 
783     /* Prepares arguments to be passed to SROM API */
784     if (Cy_Flash_BoundsCheck(sectorAddr) != false)
785     {
786         SystemCoreClockUpdate();
787 
788         flashContext.opcode = CY_FLASH_OPCODE_ERASE_SECTOR | CY_FLASH_BLOCKING_MODE;
789         flashContext.arg1 = sectorAddr;
790         flashContext.arg2 = 0UL;
791         flashContext.arg3 = 0UL;
792 
793         if (cy_device->flashEraseDelay != 0U)
794         {
795             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
796         }
797         else
798         {
799             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
800         }
801     }
802 
803     return (result);
804 }
805 
806 
807 /*******************************************************************************
808 * Function Name: Cy_Flash_StartEraseSector
809 ****************************************************************************//**
810 *
811 * Starts erasing a sector of flash. Returns immediately
812 * and reports a successful start or reason for failure.
813 * Reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
814 * by another process. User firmware should not enter the Hibernate or Deep Sleep mode until
815 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
816 * During the flash operation, the device should not be reset, including the
817 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
818 * detect circuits should be configured to generate an interrupt instead of a reset.
819 * Otherwise, portions of flash may undergo unexpected changes.
820 * \note Before reading data from previously programmed/erased flash rows, the
821 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
822 * function.
823 * \note  A Read while Write violation occurs when a flash Read operation is initiated
824 * in the same or neighboring flash sector where the flash Write, Erase, or
825 * Program operation is working. This violation may cause a HardFault exception.
826 * To avoid the Read while Write violation,
827 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
828 *
829 * \param sectorAddr Address of the flash row number.
830 * The Read-while-Write violation occurs when the flash read operation is
831 * initiated in the same flash sector where the flash erase operation is
832 * performing. Refer to the device datasheet for the details.
833 * Address must match row start address.
834 *
835 * \return Returns the status of the Flash operation,
836 * see \ref cy_en_flashdrv_status_t.
837 *
838 *******************************************************************************/
Cy_Flash_StartEraseSector(uint32_t sectorAddr)839 cy_en_flashdrv_status_t Cy_Flash_StartEraseSector(uint32_t sectorAddr)
840 {
841     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
842 
843     if (Cy_Flash_BoundsCheck(sectorAddr) != false)
844     {
845         SystemCoreClockUpdate();
846 
847         /* Prepares arguments to be passed to SROM API */
848         flashContext.opcode = CY_FLASH_OPCODE_ERASE_SECTOR;
849         if (SFLASH_SINGLE_CORE != 0U)
850         {
851             flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
852         }
853 
854         flashContext.arg1 = sectorAddr;
855         flashContext.arg2 = 0UL;
856         flashContext.arg3 = 0UL;
857 
858         if (cy_device->flashEraseDelay != 0U)
859         {
860             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
861         }
862         else
863         {
864             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
865         }
866     }
867 
868     return (result);
869 }
870 
871 
872 /*******************************************************************************
873 * Function Name: Cy_Flash_EraseSubsector
874 ****************************************************************************//**
875 *
876 * This function erases an 8-row subsector of flash. Reports success or
877 * a reason for failure. Does not return until the Write operation is
878 * complete. Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in
879 * the case when another process is writing to flash or erasing the row.
880 * User firmware should not enter the Hibernate or Deep-Sleep mode until flash Erase
881 * is complete. The Flash operation is allowed in Sleep mode.
882 * During the Flash operation, the device should not be reset, including the
883 * XRES pin, a software reset, and watchdog reset sources. Also, low-voltage
884 * detect circuits should be configured to generate an interrupt instead of a
885 * reset. Otherwise, portions of flash may undergo unexpected changes.
886 * \note  A Read while Write violation occurs when a flash Read operation is initiated
887 * in the same or neighboring flash sector where the flash Write, Erase, or
888 * Program operation is working. This violation may cause a HardFault exception.
889 * To avoid the Read while Write violation,
890 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
891 *
892 * \param subSectorAddr Address of the flash row number.
893 * The Read-while-Write violation occurs when the flash read operation is
894 * initiated in the same flash sector where the flash write operation is
895 * performing. Refer to the device datasheet for the details.
896 * Address must match row start address.
897 *
898 * \return Returns the status of the Flash operation,
899 * see \ref cy_en_flashdrv_status_t.
900 *
901 *******************************************************************************/
Cy_Flash_EraseSubsector(uint32_t subSectorAddr)902 cy_en_flashdrv_status_t Cy_Flash_EraseSubsector(uint32_t subSectorAddr)
903 {
904     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
905 
906     /* Prepares arguments to be passed to SROM API */
907     if (Cy_Flash_BoundsCheck(subSectorAddr) != false)
908     {
909         SystemCoreClockUpdate();
910 
911         flashContext.opcode = CY_FLASH_OPCODE_ERASE_SUB_SECTOR | CY_FLASH_BLOCKING_MODE;
912         flashContext.arg1 = subSectorAddr;
913         flashContext.arg2 = 0UL;
914         flashContext.arg3 = 0UL;
915 
916         if (cy_device->flashEraseDelay != 0U)
917         {
918             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
919         }
920         else
921         {
922             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
923         }
924     }
925 
926     return (result);
927 }
928 
929 
930 /*******************************************************************************
931 * Function Name: Cy_Flash_StartEraseSubsector
932 ****************************************************************************//**
933 *
934 * Starts erasing an 8-row subsector of flash. Returns immediately
935 * and reports a successful start or reason for failure.
936 * Reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case when IPC structure is locked
937 * by another process. User firmware should not enter the Hibernate or Deep-Sleep mode until
938 * flash Erase is complete. The Flash operation is allowed in Sleep mode.
939 * During the flash operation, the device should not be reset, including the
940 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
941 * detect circuits should be configured to generate an interrupt instead of a reset.
942 * Otherwise, portions of flash may undergo unexpected changes.
943 * \note Before reading data from previously programmed/erased flash rows, the
944 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
945 * function.
946 * \note  A Read while Write violation occurs when a flash Read operation is initiated
947 * in the same or neighboring flash sector where the flash Write, Erase, or
948 * Program operation is working. This violation may cause a HardFault exception.
949 * To avoid the Read while Write violation,
950 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
951 *
952 * \param subSectorAddr Address of the flash row number.
953 * The Read-while-Write violation occurs when the flash read operation is
954 * initiated in the same flash sector where the flash erase operation is
955 * performing. Refer to the device datasheet for the details.
956 * Address must match row start address.
957 *
958 * \return Returns the status of the Flash operation,
959 * see \ref cy_en_flashdrv_status_t.
960 *
961 *******************************************************************************/
Cy_Flash_StartEraseSubsector(uint32_t subSectorAddr)962 cy_en_flashdrv_status_t Cy_Flash_StartEraseSubsector(uint32_t subSectorAddr)
963 {
964     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
965 
966     if (Cy_Flash_BoundsCheck(subSectorAddr) != false)
967     {
968         SystemCoreClockUpdate();
969 
970         /* Prepares arguments to be passed to SROM API */
971         flashContext.opcode = CY_FLASH_OPCODE_ERASE_SUB_SECTOR;
972         if (SFLASH_SINGLE_CORE != 0U)
973         {
974             flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
975         }
976 
977         flashContext.arg1 = subSectorAddr;
978         flashContext.arg2 = 0UL;
979         flashContext.arg3 = 0UL;
980 
981         if (cy_device->flashEraseDelay != 0U)
982         {
983             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_ERASE_DELAY);
984         }
985         else
986         {
987             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
988         }
989     }
990 
991     return (result);
992 }
993 
994 
995 /*******************************************************************************
996 * Function Name: Cy_Flash_ProgramRow
997 ****************************************************************************//**
998 *
999 * This function writes an array of data to a single row of flash. Reports
1000 * success or a reason for failure. Does not return until the Program operation
1001 * is complete.
1002 * Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case
1003 * when another process is writing to flash. User firmware should not enter the
1004 * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation
1005 * is allowed in Sleep mode. During the Flash operation, the device should not be
1006 * reset, including the XRES pin, a software reset, and watchdog reset sources.
1007 * Also, low-voltage detect circuits should be configured to generate an interrupt
1008 * instead of a reset. Otherwise, portions of flash may undergo unexpected
1009 * changes.\n
1010 * Before calling this function, the target flash region must be erased by
1011 * the StartErase/EraseRow function.\n
1012 * Data to be programmed must be located in the SRAM memory region.
1013 * \note Before reading data from previously programmed/erased flash rows, the
1014 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
1015 * function.
1016 * \note  A Read while Write violation occurs when a flash Read operation is initiated
1017 * in the same or neighboring flash sector where the flash Write, Erase, or
1018 * Program operation is working. This violation may cause a HardFault exception.
1019 * To avoid the Read while Write violation,
1020 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
1021 *
1022 * \param rowAddr Address of the flash row number.
1023 * The Read-while-Write violation occurs when the flash read operation is
1024 * initiated in the same flash sector where the flash write operation is
1025 * performing. Refer to the device datasheet for the details.
1026 * Address must match row start address.
1027 *
1028 * \param data The pointer to the data which has to be written to flash. The size
1029 * of the data array must be equal to the flash row size. The flash row size for
1030 * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
1031 * the device datasheet for the details.
1032 *
1033 * \return Returns the status of the Flash operation,
1034 * see \ref cy_en_flashdrv_status_t.
1035 *
1036 *******************************************************************************/
Cy_Flash_ProgramRow(uint32_t rowAddr,const uint32_t * data)1037 cy_en_flashdrv_status_t Cy_Flash_ProgramRow(uint32_t rowAddr, const uint32_t* data)
1038 {
1039     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1040 
1041     /* Checks whether the input parameters are valid */
1042     if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1043     {
1044         SystemCoreClockUpdate();
1045 
1046         /* Prepares arguments to be passed to SROM API */
1047         flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW | CY_FLASH_BLOCKING_MODE;
1048         flashContext.arg1   = CY_FLASH_DATA_LOC_SRAM;
1049         flashContext.arg2   = rowAddr;
1050         flashContext.arg3   = (uint32_t)data;
1051 
1052         if (cy_device->flashProgramDelay != 0U)
1053         {
1054             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY);
1055         }
1056         else
1057         {
1058             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
1059         }
1060     }
1061 
1062     return (result);
1063 }
1064 
1065 
1066 /*******************************************************************************
1067 * Function Name: Cy_Flash_WriteRow
1068 ****************************************************************************//**
1069 *
1070 * This function writes an array of data to a single row of flash. This is done
1071 * in three steps - pre-program, erase and then program flash row with the input
1072 * data. Reports success or a reason for failure. Does not return until the Write
1073 * operation is complete.
1074 * Returns immediately and reports a \ref CY_FLASH_DRV_IPC_BUSY error in the case
1075 * when another process is writing to flash. User firmware should not enter the
1076 * Hibernate or Deep-sleep mode until flash Write is complete. The Flash operation
1077 * is allowed in Sleep mode. During the Flash operation, the
1078 * device should not be reset, including the XRES pin, a software
1079 * reset, and watchdog reset sources. Also, low-voltage detect
1080 * circuits should be configured to generate an interrupt
1081 * instead of a reset. Otherwise, portions of flash may undergo
1082 * unexpected changes.
1083 * \note  A Read while Write violation occurs when a flash Read operation is initiated
1084 * in the same or neighboring flash sector where the flash Write, Erase, or
1085 * Program operation is working. This violation may cause a HardFault exception.
1086 * To avoid the Read while Write violation,
1087 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
1088 *
1089 * \param rowAddr Address of the flash row number.
1090 * The Read-while-Write violation occurs when the flash read operation is
1091 * initiated in the same flash sector where the flash write operation is
1092 * performing. Refer to the device datasheet for the details.
1093 * Address must match row start address.
1094 *
1095 * \param data The pointer to the data which has to be written to flash. The size
1096 * of the data array must be equal to the flash row size. The flash row size for
1097 * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
1098 * the device datasheet for the details.
1099 *
1100 * \return Returns the status of the Flash operation,
1101 * see \ref cy_en_flashdrv_status_t.
1102 *
1103 *******************************************************************************/
Cy_Flash_WriteRow(uint32_t rowAddr,const uint32_t * data)1104 cy_en_flashdrv_status_t Cy_Flash_WriteRow(uint32_t rowAddr, const uint32_t* data)
1105 {
1106     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1107 
1108     /* Checks whether the input parameters are valid */
1109     if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1110     {
1111         SystemCoreClockUpdate();
1112 
1113         /* Prepares arguments to be passed to SROM API */
1114         flashContext.opcode = CY_FLASH_OPCODE_WRITE_ROW | CY_FLASH_BLOCKING_MODE;
1115         flashContext.arg1   = 0UL;
1116         flashContext.arg2   = rowAddr;
1117         flashContext.arg3   = (uint32_t)data;
1118 
1119         if (cy_device->flashWriteDelay != 0U)
1120         {
1121             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_START_WRITE_DELAY);
1122         }
1123         else
1124         {
1125             result = Cy_Flash_SendCmd(CY_FLASH_BLOCKING_MODE, CY_FLASH_NO_DELAY);
1126         }
1127     }
1128 
1129     return (result);
1130 }
1131 
1132 
1133 /*******************************************************************************
1134 * Function Name: Cy_Flash_StartWrite
1135 ****************************************************************************//**
1136 *
1137 * Performs pre-program, erase and then starts programming the flash row with
1138 * the input data. Returns immediately and reports a successful start
1139 * or reason for failure. Reports a \ref CY_FLASH_DRV_IPC_BUSY error
1140 * in the case when another process is writing to flash. User
1141 * firmware should not enter the Hibernate or Deep-Sleep mode until
1142 * flash Write is complete. The Flash operation is allowed in Sleep mode.
1143 * During the flash operation, the device should not be reset, including the
1144 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
1145 * detect circuits should be configured to generate an interrupt instead of a reset.
1146 * Otherwise, portions of flash may undergo unexpected changes.
1147 * \note Before reading data from previously programmed/erased flash rows, the
1148 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
1149 * function.
1150 * \note  A Read while Write violation occurs when a flash Read operation is initiated
1151 * in the same or neighboring flash sector where the flash Write, Erase, or
1152 * Program operation is working. This violation may cause a HardFault exception.
1153 * To avoid the Read while Write violation,
1154 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
1155 *
1156 * \param rowAddr Address of the flash row number.
1157 * The Read-while-Write violation occurs when the flash read operation is
1158 * initiated in the same flash sector where the flash write operation is
1159 * performing. Refer to the device datasheet for the details.
1160 * Address must match row start address.
1161 *
1162 * \param data The pointer to the data to be written to flash. The size
1163 * of the data array must be equal to the flash row size. The flash row size for
1164 * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
1165 * the device datasheet for the details.
1166 *
1167 * \return Returns the status of the Flash operation,
1168 * see \ref cy_en_flashdrv_status_t.
1169 *
1170 *******************************************************************************/
Cy_Flash_StartWrite(uint32_t rowAddr,const uint32_t * data)1171 cy_en_flashdrv_status_t Cy_Flash_StartWrite(uint32_t rowAddr, const uint32_t* data)
1172 {
1173     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1174 
1175     /* Checks whether the input parameters are valid */
1176     if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1177     {
1178         result = Cy_Flash_StartEraseRow(rowAddr);
1179 
1180         if (CY_FLASH_DRV_OPERATION_STARTED == result)
1181         {
1182             /* Polls whether the IPC is released and the Flash operation is performed */
1183             do
1184             {
1185                 result = Cy_Flash_OperationStatus();
1186             }
1187             while (result == CY_FLASH_DRV_OPCODE_BUSY);
1188 
1189             if (CY_FLASH_DRV_SUCCESS == result)
1190             {
1191                 result = Cy_Flash_StartProgram(rowAddr, data);
1192             }
1193         }
1194     }
1195 
1196     return (result);
1197 }
1198 
1199 
1200 /*******************************************************************************
1201 * Function Name: Cy_Flash_IsOperationComplete
1202 ****************************************************************************//**
1203 *
1204 * Reports a successful operation result, reason of failure or busy status
1205 * ( \ref CY_FLASH_DRV_OPCODE_BUSY ).
1206 *
1207 * \return Returns the status of the Flash operation (see \ref cy_en_flashdrv_status_t).
1208 *
1209 *******************************************************************************/
Cy_Flash_IsOperationComplete(void)1210 cy_en_flashdrv_status_t Cy_Flash_IsOperationComplete(void)
1211 {
1212     return (Cy_Flash_OperationStatus());
1213 }
1214 
1215 
1216 /*******************************************************************************
1217 * Function Name: Cy_Flash_StartProgram
1218 ****************************************************************************//**
1219 *
1220 * Starts writing an array of data to a single row of flash. Returns immediately
1221 * and reports a successful start or reason for failure.
1222 * Reports a \ref CY_FLASH_DRV_IPC_BUSY error if another process is writing
1223 * to flash. The user firmware should not enter Hibernate or Deep-Sleep mode until flash
1224 * Program is complete. The Flash operation is allowed in Sleep mode.
1225 * During the Flash operation, the device should not be reset, including the
1226 * XRES pin, a software reset, and watchdog reset sources. Also, the low-voltage
1227 * detect circuits should be configured to generate an interrupt instead of a reset.
1228 * Otherwise, portions of flash may undergo unexpected changes.\n
1229 * Before calling this function, the target flash region must be erased by
1230 * the StartEraseRow/EraseRow function.\n
1231 * Data to be programmed must be located in the SRAM memory region.
1232 * \note Before reading data from previously programmed/erased flash rows, the
1233 * user must clear the flash cache with the Cy_SysLib_ClearFlashCacheAndBuffer()
1234 * function.
1235 * \note  A Read while Write violation occurs when a flash Read operation is initiated
1236 * in the same or neighboring flash sector where the flash Write, Erase, or
1237 * Program operation is working. This violation may cause a HardFault exception.
1238 * To avoid the Read while Write violation,
1239 * use Cy_Flash_IsOperationComplete() to ensure flash operation is complete.
1240 *
1241 * \param rowAddr The address of the flash row number.
1242 * The Read-while-Write violation occurs when the Flash Write operation is
1243 * performing. Refer to the device datasheet for the details.
1244 * The address must match the row start address.
1245 *
1246 * \param data The pointer to the data to be written to flash. The size
1247 * of the data array must be equal to the flash row size. The flash row size for
1248 * the selected device is defined by the \ref CY_FLASH_SIZEOF_ROW macro. Refer to
1249 * the device datasheet for the details.
1250 *
1251 * \return Returns the status of the Flash operation,
1252 * see \ref cy_en_flashdrv_status_t.
1253 *
1254 *******************************************************************************/
Cy_Flash_StartProgram(uint32_t rowAddr,const uint32_t * data)1255 cy_en_flashdrv_status_t Cy_Flash_StartProgram(uint32_t rowAddr, const uint32_t* data)
1256 {
1257     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1258 
1259     if ((Cy_Flash_BoundsCheck(rowAddr) != false) && (NULL != data))
1260     {
1261         SystemCoreClockUpdate();
1262 
1263         /* Prepares arguments to be passed to SROM API */
1264         flashContext.opcode = CY_FLASH_OPCODE_PROGRAM_ROW;
1265 
1266         if (SFLASH_SINGLE_CORE != 0U)
1267         {
1268             flashContext.opcode |= CY_FLASH_BLOCKING_MODE;
1269         }
1270 
1271         flashContext.arg1   = CY_FLASH_DATA_LOC_SRAM;
1272         flashContext.arg2   = rowAddr;
1273         flashContext.arg3   = (uint32_t)data;
1274 
1275         if (cy_device->flashProgramDelay != 0U)
1276         {
1277             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_START_PROGRAM_DELAY);
1278         }
1279         else
1280         {
1281             result = Cy_Flash_SendCmd(CY_FLASH_NON_BLOCKING_MODE, CY_FLASH_NO_DELAY);
1282         }
1283     }
1284 
1285     return (result);
1286 }
1287 
1288 
1289 /*******************************************************************************
1290 * Function Name: Cy_Flash_RowChecksum
1291 ****************************************************************************//**
1292 *
1293 * Returns a checksum value of the specified flash row.
1294 *
1295 * \note Now Cy_Flash_RowChecksum() requires the row <b>address</b> (rowAddr)
1296 *       as a parameter. In previous versions of the driver, this function used
1297 *       the row <b>number</b> (rowNum) for this parameter.
1298 *
1299 * \param rowAddr The address of the flash row.
1300 *
1301 * \param checksumPtr The pointer to the address where checksum is to be stored
1302 *
1303 * \return Returns the status of the Flash operation.
1304 *
1305 *******************************************************************************/
Cy_Flash_RowChecksum(uint32_t rowAddr,uint32_t * checksumPtr)1306 cy_en_flashdrv_status_t Cy_Flash_RowChecksum (uint32_t rowAddr, uint32_t* checksumPtr)
1307 {
1308     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1309     uint32_t resTmp;
1310     uint32_t rowID;
1311 
1312     /* Checks whether the input parameters are valid */
1313     if ((Cy_Flash_BoundsCheck(rowAddr)) && (NULL != checksumPtr))
1314     {
1315         rowID = Cy_Flash_GetRowNum(rowAddr);
1316 
1317         /* Prepares arguments to be passed to SROM API */
1318         flashContext.opcode = CY_FLASH_OPCODE_CHECKSUM |
1319                               (((rowID >> CY_FLASH_REGION_ID_SHIFT) & CY_FLASH_REGION_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_REGION_SHIFT) |
1320                               ((rowID & CY_FLASH_ROW_ID_MASK) << CY_FLASH_OPCODE_CHECKSUM_ROW_SHIFT);
1321 
1322         /* Tries to acquire the IPC structure and pass the arguments to SROM API */
1323         if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0,
1324                                   (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
1325         {
1326             /* Polls whether IPC is released and the Flash operation is performed */
1327             while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false)
1328             {
1329                 /* Wait till IPC is released */
1330             }
1331 
1332             resTmp = flashContext.opcode >> CY_FLASH_ERROR_SHIFT;
1333 
1334             if (resTmp == CY_FLASH_ERROR_NO_ERROR)
1335             {
1336                 result = CY_FLASH_DRV_SUCCESS;
1337 
1338                 if (CY_IPC_V1)
1339                 {
1340                     *checksumPtr = flashContext.opcode & CY_FLASH_RESULT_MASK;
1341                 }
1342                 else
1343                 {
1344                     *checksumPtr = REG_IPC_STRUCT_DATA1(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL));
1345                 }
1346             }
1347             else
1348             {
1349                 result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1350             }
1351 
1352         }
1353         else
1354         {
1355             /* The IPC structure is already locked by another process */
1356             result = CY_FLASH_DRV_IPC_BUSY;
1357         }
1358     }
1359 
1360     return (result);
1361 }
1362 
1363 
1364 /*******************************************************************************
1365 * Function Name: Cy_Flash_CalculateHash
1366 ****************************************************************************//**
1367 *
1368 * Returns a hash value of the specified region of flash.
1369 *
1370 * \param data Start the data address.
1371 *
1372 * \param numberOfBytes The hash value is calculated for the number of bytes after the
1373 * start data address (0 - 1 byte, 1- 2 bytes etc).
1374 *
1375 * \param hashPtr The pointer to the address where hash is to be stored
1376 *
1377 * \return Returns the status of the Flash operation.
1378 *
1379 *******************************************************************************/
Cy_Flash_CalculateHash(const uint32_t * data,uint32_t numberOfBytes,uint32_t * hashPtr)1380 cy_en_flashdrv_status_t Cy_Flash_CalculateHash (const uint32_t* data, uint32_t numberOfBytes,  uint32_t* hashPtr)
1381 {
1382     cy_en_flashdrv_status_t result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1383     volatile uint32_t resTmp;
1384 
1385     /* Checks whether the input parameters are valid */
1386     if ((data != NULL) && (0UL != numberOfBytes))
1387     {
1388         /* Prepares arguments to be passed to SROM API */
1389         flashContext.opcode = CY_FLASH_OPCODE_HASH;
1390         flashContext.arg1 = (uint32_t)data;
1391         flashContext.arg2 = numberOfBytes;
1392 
1393         /* Tries to acquire the IPC structure and pass the arguments to SROM API */
1394         if (Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL), CY_FLASH_IPC_NOTIFY_STRUCT0,
1395                                   (void*)&flashContext) == CY_IPC_DRV_SUCCESS)
1396         {
1397             /* Polls whether IPC is released and the Flash operation is performed */
1398             while (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) != false)
1399             {
1400                 /* Wait till IPC is released */
1401             }
1402 
1403             resTmp = flashContext.opcode;
1404 
1405             if ((resTmp >> CY_FLASH_ERROR_SHIFT) == CY_FLASH_ERROR_NO_ERROR)
1406             {
1407                 result = CY_FLASH_DRV_SUCCESS;
1408                 *hashPtr = flashContext.opcode & CY_FLASH_RESULT_MASK;
1409             }
1410             else
1411             {
1412                 result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1413             }
1414         }
1415         else
1416         {
1417             /* The IPC structure is already locked by another process */
1418             result = CY_FLASH_DRV_IPC_BUSY;
1419         }
1420     }
1421 
1422     return (result);
1423 }
1424 
1425 
1426 /*******************************************************************************
1427 * Function Name: Cy_Flash_GetRowNum
1428 ****************************************************************************//**
1429 *
1430 * Returns flash region ID and row number of the Flash address.
1431 *
1432 * \param flashAddr Address to be checked
1433 *
1434 * \return
1435 *   The valid return value is encoded as follows
1436 *   <table>
1437 *   <tr><th>Field            <th>Value
1438 *   <tr><td>Flash row number <td>[15:0]  bits
1439 *   <tr><td>Flash region ID  <td>[31:16] bits
1440 *   </table>
1441 *
1442 *******************************************************************************/
Cy_Flash_GetRowNum(uint32_t flashAddr)1443 static uint32_t Cy_Flash_GetRowNum(uint32_t flashAddr)
1444 {
1445     uint32_t result;
1446 
1447 #if (CY_EM_EEPROM_SIZE>0)
1448     if ((flashAddr >= CY_EM_EEPROM_BASE) && (flashAddr < (CY_EM_EEPROM_BASE + CY_EM_EEPROM_SIZE)))
1449     {
1450         result = (CY_FLASH_REGION_ID_EM_EEPROM << CY_FLASH_REGION_ID_SHIFT) |
1451                  ((flashAddr - CY_EM_EEPROM_BASE) / CY_FLASH_SIZEOF_ROW);
1452     }
1453     else
1454 #endif
1455     if ((flashAddr >= SFLASH_BASE) && (flashAddr < (SFLASH_BASE + SFLASH_SECTION_SIZE)))
1456     {
1457         result = (CY_FLASH_REGION_ID_SFLASH << CY_FLASH_REGION_ID_SHIFT) |
1458                  ((flashAddr - SFLASH_BASE) / CY_FLASH_SIZEOF_ROW);
1459     }
1460     else
1461     {
1462         result = (CY_FLASH_REGION_ID_MAIN << CY_FLASH_REGION_ID_SHIFT) |
1463                  ((flashAddr - CY_FLASH_BASE) / CY_FLASH_SIZEOF_ROW);
1464     }
1465 
1466     return (result);
1467 }
1468 
1469 
1470 /*******************************************************************************
1471 * Function Name: Cy_Flash_BoundsCheck
1472 ****************************************************************************//**
1473 *
1474 * The function checks the following conditions:
1475 *  - if Flash address is equal to start address of the row
1476 *
1477 * \param flashAddr Address to be checked
1478 *
1479 * \return false - out of bound, true - in flash bounds
1480 *
1481 *******************************************************************************/
Cy_Flash_BoundsCheck(uint32_t flashAddr)1482 static bool Cy_Flash_BoundsCheck(uint32_t flashAddr)
1483 {
1484     return ((flashAddr % CY_FLASH_SIZEOF_ROW) == 0UL);
1485 }
1486 
1487 
1488 /*******************************************************************************
1489 * Function Name: Cy_Flash_ProcessOpcode
1490 ****************************************************************************//**
1491 *
1492 * Converts System Call returns to the Flash driver return defines.
1493 *
1494 * \param opcode The value returned by the System Call.
1495 *
1496 * \return Flash driver return.
1497 *
1498 *******************************************************************************/
Cy_Flash_ProcessOpcode(uint32_t opcode)1499 static cy_en_flashdrv_status_t Cy_Flash_ProcessOpcode(uint32_t opcode)
1500 {
1501     cy_en_flashdrv_status_t result;
1502 
1503     switch (opcode)
1504     {
1505         case 0UL:
1506         {
1507             result = CY_FLASH_DRV_SUCCESS;
1508             break;
1509         }
1510         case CY_FLASH_ROMCODE_SUCCESS:
1511         {
1512             result = CY_FLASH_DRV_SUCCESS;
1513             break;
1514         }
1515         case CY_FLASH_ROMCODE_INVALID_PROTECTION:
1516         {
1517             result = CY_FLASH_DRV_INV_PROT;
1518             break;
1519         }
1520         case CY_FLASH_ROMCODE_INVALID_FM_PL:
1521         {
1522             result = CY_FLASH_DRV_INVALID_FM_PL;
1523             break;
1524         }
1525         case CY_FLASH_ROMCODE_INVALID_FLASH_ADDR:
1526         {
1527             result = CY_FLASH_DRV_INVALID_FLASH_ADDR;
1528             break;
1529         }
1530         case CY_FLASH_ROMCODE_ROW_PROTECTED:
1531         {
1532             result = CY_FLASH_DRV_ROW_PROTECTED;
1533             break;
1534         }
1535         case CY_FLASH_ROMCODE_IN_PROGRESS_NO_ERROR:
1536         {
1537             result = CY_FLASH_DRV_PROGRESS_NO_ERROR;
1538             break;
1539         }
1540         case (uint32_t)CY_FLASH_DRV_INVALID_INPUT_PARAMETERS:
1541         {
1542             result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1543             break;
1544         }
1545         case CY_FLASH_IS_OPERATION_STARTED :
1546         {
1547             result = CY_FLASH_DRV_OPERATION_STARTED;
1548             break;
1549         }
1550         case CY_FLASH_IS_BUSY :
1551         {
1552             result = CY_FLASH_DRV_OPCODE_BUSY;
1553             break;
1554         }
1555         case CY_FLASH_IS_IPC_BUSY :
1556         {
1557             result = CY_FLASH_DRV_IPC_BUSY;
1558             break;
1559         }
1560         case CY_FLASH_IS_INVALID_INPUT_PARAMETERS :
1561         {
1562             result = CY_FLASH_DRV_INVALID_INPUT_PARAMETERS;
1563             break;
1564         }
1565         default:
1566         {
1567             result = CY_FLASH_DRV_ERR_UNC;
1568             break;
1569         }
1570     }
1571 
1572     return (result);
1573 }
1574 
1575 
1576 /*******************************************************************************
1577 * Function Name: Cy_Flash_OperationStatus
1578 ****************************************************************************//**
1579 *
1580 * Checks the status of the Flash Operation, and returns it.
1581 *
1582 * \return Returns the status of the Flash operation
1583 * (see \ref cy_en_flashdrv_status_t).
1584 *
1585 *******************************************************************************/
Cy_Flash_OperationStatus(void)1586 static cy_en_flashdrv_status_t Cy_Flash_OperationStatus(void)
1587 {
1588     cy_en_flashdrv_status_t result = CY_FLASH_DRV_OPCODE_BUSY;
1589 
1590     /* Checks if the IPC structure is not locked */
1591     if (Cy_IPC_Drv_IsLockAcquired(Cy_IPC_Drv_GetIpcBaseAddress(CY_IPC_CHAN_SYSCALL)) == false)
1592     {
1593         /* The result of SROM API calling is returned to the driver context */
1594         result = Cy_Flash_ProcessOpcode(flashContext.opcode);
1595 
1596         /* Clear pre-fetch cache after flash operation */
1597         #if CY_CPU_CORTEX_M4 && defined (CY_DEVICE_SECURE)
1598             CY_PRA_REG32_SET(CY_PRA_INDX_FLASHC_FLASH_CMD, FLASHC_FLASH_CMD_INV_Msk);
1599             while (CY_PRA_REG32_GET(CY_PRA_INDX_FLASHC_FLASH_CMD) != 0U)
1600             {
1601             }
1602         #else
1603             FLASHC_FLASH_CMD = FLASHC_FLASH_CMD_INV_Msk;
1604             while (FLASHC_FLASH_CMD != 0U)
1605             {
1606             }
1607         #endif /* CY_CPU_CORTEX_M4 && defined (CY_DEVICE_SECURE) */
1608     }
1609 
1610     return (result);
1611 }
1612 
1613 
1614 /*******************************************************************************
1615 * Function Name: Cy_Flash_GetExternalStatus
1616 ****************************************************************************//**
1617 *
1618 * This function handles the case where a module such as security image captures
1619 * a system call from this driver and reports its own status or error code,
1620 * for example protection violation. In that case, a function from this
1621 * driver returns an unknown error (see \ref cy_en_flashdrv_status_t). After receipt
1622 * of an unknown error, the user may call this function to get the status
1623 * of the capturing module.
1624 *
1625 * The user is responsible for parsing the content of the returned value
1626 * and casting it to the appropriate enumeration.
1627 *
1628 * \return
1629 * The error code that was stored in the opcode variable.
1630 *
1631 *******************************************************************************/
Cy_Flash_GetExternalStatus(void)1632 uint32_t Cy_Flash_GetExternalStatus(void)
1633 {
1634     return (flashContext.opcode);
1635 }
1636 
1637 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3');
1638 #endif /* CY_IP_M4CPUSS */
1639 
1640 /* [] END OF FILE */
1641