1 /***************************************************************************//**
2 * \file cyhal_nvm.c
3 *
4 * Description:
5 * Provides a high level interface for interacting with the Infineon embedded
6 * non-volatile memory (NVM). This is wrapper around the lower level PDL API.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation
12 *
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 *     http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27 
28 #include "cyhal_hwmgr.h"
29 #include "cyhal_hw_types.h"
30 #include "cyhal_nvm.h"
31 #include "cy_utils.h"
32 #include "cyhal_syspm.h"
33 #include "cyhal_utils_impl.h"
34 #include "cyhal_irq_impl.h"
35 #include <string.h>
36 
37 #if (CYHAL_DRIVER_AVAILABLE_FLASH)
38 #include "cyhal_flash.h"
39 #endif /* (CYHAL_DRIVER_AVAILABLE_FLASH) */
40 
41 
42 #if (CYHAL_DRIVER_AVAILABLE_NVM)
43 
44 #if defined(__cplusplus)
45 extern "C" {
46 #endif /* __cplusplus */
47 
48 #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
49 static uint16_t _cyhal_nvm_init_count = 0;
50 typedef cy_en_flashdrv_status_t (*_cyhal_flash_operation)(uint32_t rowAddr, const uint32_t* data);
51 
52 static bool _cyhal_flash_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg);
53 
54 #if defined(CPUSS_FLASHC_ECT)
55 #define _CYHAL_USES_ECT_FLASH (CPUSS_FLASHC_ECT == 1)
56 #else
57 #define _CYHAL_USES_ECT_FLASH (0u)
58 #endif
59 
60 #if (_CYHAL_USES_ECT_FLASH)
61 #define _CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS (4u)
62 #elif (CY_EM_EEPROM_SIZE > 0)
63 #define _CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS (2u)
64 #else
65 #define _CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS (1u)
66 #endif
67 
68 static bool _cyhal_flash_pending_pm_change = false;
69 
70 static cyhal_syspm_callback_data_t _cyhal_flash_internal_pm_cb = {
71     .callback = _cyhal_flash_pm_callback,
72     .states = (cyhal_syspm_callback_state_t)(CYHAL_SYSPM_CB_CPU_SLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP | CYHAL_SYSPM_CB_CPU_DEEPSLEEP_RAM | CYHAL_SYSPM_CB_SYSTEM_HIBERNATE | CYHAL_SYSPM_CB_SYSTEM_LOW),
73     .next = NULL,
74     .args = NULL,
75     .ignore_modes = (cyhal_syspm_callback_mode_t)(CYHAL_SYSPM_AFTER_DS_WFI_TRANSITION),
76 };
77 
_cyhal_flash_convert_status(uint32_t pdl_status)78 static inline cy_rslt_t _cyhal_flash_convert_status(uint32_t pdl_status)
79 {
80     return (pdl_status == CY_FLASH_DRV_OPERATION_STARTED) ? CY_RSLT_SUCCESS : pdl_status;
81 }
82 
83 #if defined(CY_IP_S8SRSSLT) && CY_FLASH_NON_BLOCKING_SUPPORTED
_cyhal_flash_irq_handler(void)84 static void _cyhal_flash_irq_handler(void)
85 {
86     (void) Cy_Flash_ResumeWrite();
87 }
88 #endif
89 
_cyhal_flash_pm_callback(cyhal_syspm_callback_state_t state,cyhal_syspm_callback_mode_t mode,void * callback_arg)90 static bool _cyhal_flash_pm_callback(cyhal_syspm_callback_state_t state, cyhal_syspm_callback_mode_t mode, void* callback_arg)
91 {
92     CY_UNUSED_PARAMETER(state);
93     CY_UNUSED_PARAMETER(callback_arg);
94     bool allow = true;
95 
96     switch (mode)
97     {
98         case CYHAL_SYSPM_CHECK_READY:
99             _cyhal_flash_pending_pm_change = true;
100             #if defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH) || CY_FLASH_NON_BLOCKING_SUPPORTED
101             if (CY_RSLT_SUCCESS != Cy_Flash_IsOperationComplete())
102             {
103                 #if (_CYHAL_USES_ECT_FLASH)
104                 /* The SROM API response is invalid unless a flash operation has occurred at least once.
105                    Therefore allow that case as an exception. */
106                 un_srom_api_resps_t resp = {{ 0UL }};
107                 cy_en_srom_api_status_t status = Cy_Srom_GetApiResponse(&resp);
108                 if(CY_SROM_STATUS_INVALID != status)
109                 #endif
110                 {
111                     _cyhal_flash_pending_pm_change = false;
112                     allow = false;
113                 }
114             }
115             #endif
116             break;
117         case CYHAL_SYSPM_BEFORE_TRANSITION:
118         case CYHAL_SYSPM_AFTER_TRANSITION:
119         case CYHAL_SYSPM_CHECK_FAIL:
120             _cyhal_flash_pending_pm_change = false;
121             break;
122         default:
123             /* Don't care */
124             break;
125     }
126 
127     return allow;
128 }
129 
_cyhal_flash_is_sram_address(uint32_t address)130 static inline bool _cyhal_flash_is_sram_address(uint32_t address)
131 {
132     return ((CY_SRAM_BASE <= address) && (address < (CY_SRAM_BASE + CY_SRAM_SIZE)));
133 }
134 
_cyhal_flash_run_operation(_cyhal_flash_operation operation,uint32_t address,const uint32_t * data,bool clearCache)135 static cy_rslt_t _cyhal_flash_run_operation(
136     _cyhal_flash_operation operation, uint32_t address, const uint32_t* data, bool clearCache)
137 {
138     cy_rslt_t status;
139     if (_cyhal_flash_pending_pm_change)
140         status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
141     else
142     {
143         status = (_cyhal_flash_is_sram_address((uint32_t)data))
144             ? (cy_rslt_t)_cyhal_flash_convert_status((cy_rslt_t)operation(address, data))
145             : CYHAL_NVM_RSLT_ERR_ADDRESS;
146 #if defined(CY_IP_M7CPUSS) /* PDL automatically clears cache when necessary in M7 devices */
147         CY_UNUSED_PARAMETER(clearCache);
148 #else
149         if (clearCache)
150         {
151             Cy_SysLib_ClearFlashCacheAndBuffer();
152         }
153 #endif
154     }
155 
156     return status;
157 }
158 
159 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
160 
161 #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
162 
163 #if (CY_RRAM_PROTECTED_OTP_SIZE > 0) && (CY_RRAM_GENERAL_OTP_SIZE > 0)
164 #define _CYHAL_INTERNAL_OTP_MEMORY_BLOCKS  (2u)
165 #else
166 #define _CYHAL_INTERNAL_OTP_MEMORY_BLOCKS  (1u)
167 #endif
168 
169 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
170 
171 #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
172 
173 enum {
174 #if (CY_RRAM_WORK_REGION_SIZE > 0)
175     _CYHAL_RRAM_WORK_REGION,
176 #endif
177 #if (CY_RRAM_SFLASH_REGION_SIZE > 0)
178     _CYHAL_RRAM_SFLASH_REGION,
179 #endif
180 #if (CY_RRAM_PROTECTED_REGION_SIZE > 0)
181     _CYHAL_RRAM_PROTECTED_REGION,
182 #endif
183 #if (CY_RRAM_MAIN_REGION_SIZE > 0)
184     _CYHAL_RRAM_MAIN_REGION,
185 #endif
186     _CYHAL_RRAM_REGION_COUNT
187 } _cyhal_rram_regions_count;
188 
189 #define _CYHAL_INTERNAL_RRAM_MEMORY_BLOCKS      (_CYHAL_RRAM_REGION_COUNT)
190 
_cyhal_rram_is_busy()191 __STATIC_INLINE bool _cyhal_rram_is_busy()
192 {
193     return (bool)_FLD2VAL(RRAMC_RRAM_SFR_NVM_STATUS_BUSY, RRAM_NVM_STATUS(RRAMC0));
194 }
195 
196 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
197 
198 
199 #ifndef _CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS
200 #define _CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS     (0)
201 #endif /* (_CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS) */
202 
203 #ifndef _CYHAL_INTERNAL_RRAM_MEMORY_BLOCKS
204 #define _CYHAL_INTERNAL_RRAM_MEMORY_BLOCKS      (0)
205 #endif /* (_CYHAL_INTERNAL_RRAM_MEMORY_BLOCKS) */
206 
207 #ifndef _CYHAL_INTERNAL_OTP_MEMORY_BLOCKS
208 #define _CYHAL_INTERNAL_OTP_MEMORY_BLOCKS       (0)
209 #endif /* (_CYHAL_INTERNAL_OTP_MEMORY_BLOCKS) */
210 
211 
212 #define _CYHAL_NVM_MEMORY_BLOCKS_COUNT  (_CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS + \
213                                          _CYHAL_INTERNAL_RRAM_MEMORY_BLOCKS + \
214                                          _CYHAL_INTERNAL_OTP_MEMORY_BLOCKS)
215 
216 
217 static const cyhal_nvm_region_info_t _cyhal_nvm_mem_regions[_CYHAL_NVM_MEMORY_BLOCKS_COUNT] = {
218 #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
219     #if _CYHAL_USES_ECT_FLASH
220         /* Each flash area is divided into two regions: A "large" region with 2KB sectors and a
221         * "small" region with 128b sectors. The flash can be configured in either single- or
222         * double-bank mode. In double-bank mode, the flash is divided into two sub-regions such
223         * that it is possible to read from one region while writing to another region. Because
224         * dual-bank mode is highly device specific, for simplicity we stick to single-bank mode
225         * in the portable HAL driver */
226         // Large main flash region, 32KB sectors
227         {
228             .nvm_type = CYHAL_NVM_TYPE_FLASH,
229             .start_address = CY_FLASH_LG_SBM_BASE,
230             .size = CY_FLASH_LG_SBM_SIZE,
231             .sector_size = 32768u,
232             .block_size = 8u,
233             .is_erase_required = true,
234             .erase_value = 0xFFU,
235         },
236         // Small main flash region, 8KB sectors
237         {
238             .nvm_type = CYHAL_NVM_TYPE_FLASH,
239             .start_address = CY_FLASH_SM_SBM_BASE,
240             .size = CY_FLASH_SM_SBM_SIZE,
241             .sector_size = 8192u,
242             .block_size = 8u,
243             .is_erase_required = true,
244             .erase_value = 0xFFU,
245         },
246         // Large wflash region, 32KB sectors
247         {
248             .nvm_type = CYHAL_NVM_TYPE_FLASH,
249             .start_address = CY_WFLASH_LG_SBM_BASE,
250             .size = CY_WFLASH_LG_SBM_SIZE,
251             .sector_size = 2048u, /* Hard-coded in the IP */
252             .block_size = 4u,
253             .is_erase_required = true,
254             .erase_value = 0xFFU,
255         },
256         // Small wflash region, 128B sectors
257         {
258             .nvm_type = CYHAL_NVM_TYPE_FLASH,
259             .start_address = CY_WFLASH_SM_SBM_BASE,
260             .size = CY_WFLASH_SM_SBM_SIZE,
261             .sector_size = 128u,
262             .block_size = 4u,
263             .is_erase_required = true,
264             .erase_value = 0xFFU,
265         },
266     #else
267         // Main Flash
268         {
269             .nvm_type = CYHAL_NVM_TYPE_FLASH,
270             .start_address = CY_FLASH_BASE,
271             .size = CY_FLASH_SIZE,
272             .sector_size = CY_FLASH_SIZEOF_ROW,
273             .block_size = CY_FLASH_SIZEOF_ROW,
274             .is_erase_required = true,
275             .erase_value = 0x00U,
276         },
277         // Working Flash
278         #if (CY_EM_EEPROM_SIZE > 0)
279             {
280                 .nvm_type = CYHAL_NVM_TYPE_FLASH,
281                 .start_address = CY_EM_EEPROM_BASE,
282                 .size = CY_EM_EEPROM_SIZE,
283                 .sector_size = CY_FLASH_SIZEOF_ROW,
284                 .block_size = CY_FLASH_SIZEOF_ROW,
285                 .is_erase_required = true,
286                 .erase_value = 0x00U,
287             },
288         #endif
289     #endif /* CY_IP_M7CPUSS or other */
290 #endif /* (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
291 
292 #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
293     #if (CY_RRAM_MAIN_REGION_SIZE > 0)
294         // Main RRAM region, 8KB sectors
295         {
296             .nvm_type = CYHAL_NVM_TYPE_RRAM,
297             .start_address = CY_RRAM_MAIN_HOST_NS_START_ADDRESS,
298             .size = CY_RRAM_MAIN_REGION_SIZE,
299             .sector_size = CY_RRAM_REGION_SIZE_UNIT,
300             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
301             .is_erase_required = false,
302             .erase_value = 0x00U,
303         },
304     #endif /* (CY_RRAM_MAIN_REGION_SIZE > 0) */
305     #if (CY_RRAM_WORK_REGION_SIZE > 0)
306         // Work RRAM region, 8KB sectors
307         {
308             .nvm_type = CYHAL_NVM_TYPE_RRAM,
309             .start_address = CY_RRAM_WORK_HOST_NS_START_ADDRESS,
310             .size = CY_RRAM_WORK_REGION_SIZE,
311             .sector_size = CY_RRAM_REGION_SIZE_UNIT,
312             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
313             .is_erase_required = false,
314             .erase_value = 0x00U,
315         },
316     #endif /* (CY_RRAM_WORK_REGION_SIZE > 0) */
317     #if (CY_RRAM_SFLASH_REGION_SIZE > 0)
318         // SFALSH RRAM region, 8KB sectors
319         {
320             .nvm_type = CYHAL_NVM_TYPE_RRAM,
321             .start_address = CY_RRAM_SFLASH_HOST_NS_START_ADDRESS,
322             .size = CY_RRAM_SFLASH_REGION_SIZE,
323             .sector_size = CY_RRAM_REGION_SIZE_UNIT,
324             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
325             .is_erase_required = false,
326             .erase_value = 0x00U,
327         },
328     #endif /* (CY_RRAM_SFLASH_REGION_SIZE > 0) */
329     #if (CY_RRAM_PROTECTED_REGION_SIZE > 0)
330         // SFALSH RRAM region, 8KB sectors
331         {
332             .nvm_type = CYHAL_NVM_TYPE_RRAM,
333             .start_address = CY_RRAM_PROTECTED_HOST_NS_START_ADDRESS,
334             .size = CY_RRAM_PROTECTED_REGION_SIZE,
335             .sector_size = CY_RRAM_REGION_SIZE_UNIT,
336             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
337             .is_erase_required = false,
338             .erase_value = 0x00U,
339         },
340     #endif /* (CY_RRAM_PROTECTED_REGION_SIZE > 0) */
341 #endif /* (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
342 
343 #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
344     #if (CY_RRAM_GENERAL_OTP_SIZE > 0)
345         // General RRAM OTP region, 5.5KB sector
346         {
347             .nvm_type = CYHAL_NVM_TYPE_OTP,
348             .start_address = CY_RRAM_GENERAL_OTP_MMIO_NS_START_ADDRESS,
349             .size = CY_RRAM_GENERAL_OTP_SIZE,
350             .sector_size = 5632u,
351             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
352             .is_erase_required = false,
353             .erase_value = 0xFFU,
354         },
355     #endif /* (CY_RRAM_GENERAL_OTP_SIZE > 0) */
356     #if (CY_RRAM_PROTECTED_OTP_SIZE > 0)
357         // Protected RRAM OTP region, 8KB sector
358         {
359             .nvm_type = CYHAL_NVM_TYPE_OTP,
360             .start_address = CY_RRAM_PROTECTED_OTP_PROTECTED_NS_START_ADDRESS,
361             .size = CY_RRAM_PROTECTED_OTP_SIZE,
362             .sector_size = 8192u,
363             .block_size = CY_RRAM_BLOCK_SIZE_BYTES,
364             .is_erase_required = false,
365             .erase_value = 0xFFU,
366         },
367     #endif /* (CY_RRAM_PROTECTED_OTP_SIZE > 0) */
368 #endif /* (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
369 };
370 
371 
_cyhal_nvm_address_in_region(uint32_t address,const cyhal_nvm_region_info_t * region_info)372 static inline bool _cyhal_nvm_address_in_region(uint32_t address, const cyhal_nvm_region_info_t* region_info)
373 {
374     return (address >= region_info->start_address && address < (region_info->start_address + region_info->size));
375 }
376 
_cyhal_nvm_get_nvm_region_by_boundaries(uint32_t start_address,uint32_t end_address,cyhal_nvm_region_info_t * block_info)377 static bool _cyhal_nvm_get_nvm_region_by_boundaries(uint32_t start_address, uint32_t end_address, cyhal_nvm_region_info_t *block_info)
378 {
379     bool start_address_valid = false;
380     bool end_address_valid = false;
381     bool end_address_check_need = (end_address == 0) ? false : true;
382     memset(block_info, 0, sizeof(*block_info));
383 
384     for (uint32_t region_id = 0; region_id < _CYHAL_NVM_MEMORY_BLOCKS_COUNT; region_id++)
385     {
386         start_address_valid = _cyhal_nvm_address_in_region(start_address, &_cyhal_nvm_mem_regions[region_id]);
387         end_address_valid = (!end_address_check_need) ? true :
388             _cyhal_nvm_address_in_region(end_address, &_cyhal_nvm_mem_regions[region_id]);
389         if (start_address_valid && end_address_valid)
390         {
391             *block_info = _cyhal_nvm_mem_regions[region_id];
392             block_info->offset = start_address - _cyhal_nvm_mem_regions[region_id].start_address;
393             break;
394         }
395     }
396 
397     return (start_address_valid && end_address_valid);
398 }
399 
_cyhal_nvm_get_nvm_region_by_address(uint32_t address,cyhal_nvm_region_info_t * region_info)400 static inline bool _cyhal_nvm_get_nvm_region_by_address(uint32_t address, cyhal_nvm_region_info_t *region_info)
401 {
402     return _cyhal_nvm_get_nvm_region_by_boundaries(address, 0, region_info);
403 }
404 
405 /*******************************************************************************
406 *       Functions
407 *******************************************************************************/
408 
cyhal_nvm_init(cyhal_nvm_t * obj)409 cy_rslt_t cyhal_nvm_init(cyhal_nvm_t *obj)
410 {
411     CY_ASSERT(NULL != obj);
412     CY_UNUSED_PARAMETER(obj);
413 
414     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
415 
416 #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
417 #if defined(CY_IP_S8SRSSLT) && CY_FLASH_NON_BLOCKING_SUPPORTED
418     /* Configure Flash interrupt */
419     _cyhal_irq_register(cpuss_interrupt_spcif_IRQn, 0u, &_cyhal_flash_irq_handler);
420     _cyhal_irq_enable(cpuss_interrupt_spcif_IRQn);
421 #endif /* defined(CY_IP_S8SRSSLT) && CY_FLASH_NON_BLOCKING_SUPPORTED */
422     if(_cyhal_nvm_init_count == 0)
423     {
424     #if _CYHAL_USES_ECT_FLASH
425         // Cy_Flash_Init is only safe to call a single time after the SysPm HAL
426         // has been initialized (or anything else in the application has registered
427         // a callback). It unconditionally re-initializes its callback struct each
428         // time, which would remove any callbacks registered with lower priority.
429         static bool flash_initialized = false;
430         if(false == flash_initialized)
431         {
432             flash_initialized = true;
433             Cy_Flash_Init();
434         }
435         // Always call this, because `cyhal_nvm_free` disables the work flash write
436         Cy_Flashc_WorkWriteEnable();
437     #endif /* _CYHAL_USES_ECT_FLASH */
438     _cyhal_syspm_register_peripheral_callback(&_cyhal_flash_internal_pm_cb);
439     }
440     _cyhal_nvm_init_count++;
441     status = CY_RSLT_SUCCESS;
442 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
443 
444 #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
445     /* Nothing to do for RRAM initialization */
446     status = CY_RSLT_SUCCESS;
447 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
448 
449 #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
450     /* Nothing to do for RRAM initialization */
451     status = CY_RSLT_SUCCESS;
452 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
453 
454     return status;
455 }
456 
cyhal_nvm_free(cyhal_nvm_t * obj)457 void cyhal_nvm_free(cyhal_nvm_t *obj)
458 {
459     CY_ASSERT(NULL != obj);
460     CY_UNUSED_PARAMETER(obj);
461 
462 #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
463 #if defined(CY_IP_S8SRSSLT) && CY_FLASH_NON_BLOCKING_SUPPORTED
464     _cyhal_irq_free(cpuss_interrupt_spcif_IRQn);
465 #endif /* defined(CY_IP_S8SRSSLT) && CY_FLASH_NON_BLOCKING_SUPPORTED */
466     CY_ASSERT(_cyhal_nvm_init_count > 0);
467     _cyhal_nvm_init_count--;
468     if(_cyhal_nvm_init_count == 0)
469     {
470         _cyhal_syspm_unregister_peripheral_callback(&_cyhal_flash_internal_pm_cb);
471     #if _CYHAL_USES_ECT_FLASH
472         Cy_Flashc_WorkWriteDisable();
473     #endif /* _CYHAL_USES_ECT_FLASH */
474     }
475 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
476 
477 #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
478     /* Nothing to do for RRAM deinitialization */
479 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
480 
481 #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
482     /* Nothing to do for OTP deinitialization */
483 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
484 }
485 
cyhal_nvm_get_info(cyhal_nvm_t * obj,cyhal_nvm_info_t * info)486 void cyhal_nvm_get_info(cyhal_nvm_t *obj, cyhal_nvm_info_t *info)
487 {
488     CY_ASSERT(NULL != obj);
489     CY_ASSERT(NULL != info);
490     CY_UNUSED_PARAMETER(obj);
491 
492     info->region_count = _CYHAL_NVM_MEMORY_BLOCKS_COUNT;
493     info->regions = &_cyhal_nvm_mem_regions[0];
494 }
495 
cyhal_nvm_read(cyhal_nvm_t * obj,uint32_t address,uint8_t * data,size_t size)496 cy_rslt_t cyhal_nvm_read(cyhal_nvm_t *obj, uint32_t address, uint8_t *data, size_t size)
497 {
498     CY_ASSERT(NULL != obj);
499     CY_UNUSED_PARAMETER(obj);
500 
501     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
502     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
503 
504     bool is_address_valid = false;
505     is_address_valid = _cyhal_nvm_get_nvm_region_by_boundaries(address, (address + size - 1), &_cyhal_nvm_current_block_info);
506 
507     if (!is_address_valid)
508     {
509         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
510     }
511     else
512     {
513         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
514         {
515         #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
516             memcpy((void *)data, (void *)address, size);
517             status = CY_RSLT_SUCCESS;
518         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
519         }
520         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
521         {
522         #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
523             status = (cy_rslt_t)Cy_RRAM_NvmReadByteArray(RRAMC0, address, data, size);
524         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
525         }
526         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
527         {
528         #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
529             status = (cy_rslt_t)Cy_RRAM_OtpReadByteArray(RRAMC0, address, data, size);
530         #endif /* (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
531         }
532         else
533         {
534             /* Not supported type of NVM */
535             CY_UNUSED_PARAMETER(address);
536             CY_UNUSED_PARAMETER(data);
537             CY_UNUSED_PARAMETER(size);
538             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
539         }
540     }
541     return status;
542 }
543 
cyhal_nvm_erase(cyhal_nvm_t * obj,uint32_t address)544 cy_rslt_t cyhal_nvm_erase(cyhal_nvm_t *obj, uint32_t address)
545 {
546     CY_ASSERT(NULL != obj);
547     CY_UNUSED_PARAMETER(obj);
548 
549     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
550     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
551 
552     bool is_address_valid = false;
553     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
554 
555     if (!is_address_valid)
556     {
557         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
558     }
559     else
560     {
561         #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
562         SCB_InvalidateDCache_by_Addr((void *)address, _cyhal_nvm_current_block_info.sector_size);
563         #endif
564         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
565         {
566         #if (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH)) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
567             if (_cyhal_flash_pending_pm_change)
568             {
569                 status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
570             }
571             else
572             {
573             #if (_CYHAL_USES_ECT_FLASH)
574                 /* This IP does not support row-at-a-time erase */
575                 status = (cy_rslt_t)_cyhal_flash_convert_status(Cy_Flash_EraseSector(address));
576             #else
577                 status = (cy_rslt_t)_cyhal_flash_convert_status(Cy_Flash_EraseRow(address));
578             #endif
579 
580 			#if !defined(CY_IP_M7CPUSS)
581 				Cy_SysLib_ClearFlashCacheAndBuffer();
582 			#endif
583 			/* PDL automatically clears cache when necessary in M7 devices */
584             }
585         #else
586             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
587         #endif /* (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH)) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
588         }
589         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
590         {
591             /* Erase operation not needed for RRAM */
592             status = CY_RSLT_SUCCESS;
593         }
594         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
595         {
596             /* Not supported for OTP */
597             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
598         }
599         else
600         {
601             /* Not supported type of NVM */
602             CY_UNUSED_PARAMETER(address);
603             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
604         }
605     }
606     return status;
607 }
608 
cyhal_nvm_write(cyhal_nvm_t * obj,uint32_t address,const uint32_t * data)609 cy_rslt_t cyhal_nvm_write(cyhal_nvm_t *obj, uint32_t address, const uint32_t* data)
610 {
611     CY_ASSERT(NULL != obj);
612     CY_UNUSED_PARAMETER(obj);
613 
614     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
615     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
616 
617     bool is_address_valid = false;
618     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
619 
620     if (!is_address_valid)
621     {
622         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
623     }
624     else
625     {
626         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
627         {
628         #if !(_CYHAL_USES_ECT_FLASH) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
629             status = _cyhal_flash_run_operation(Cy_Flash_WriteRow, address, data, true);
630         #else
631             /* CY_IP_M7CPUSS does not support a bundled write (erase + program) operation. Instead,
632             * it is necessary to perform an erase operation followed by a program operation.
633             */
634             CY_UNUSED_PARAMETER(address);
635             CY_UNUSED_PARAMETER(data);
636             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
637         #endif /* !(_CYHAL_USES_ECT_FLASH) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
638         }
639         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
640         {
641         #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
642             status = (cy_rslt_t)Cy_RRAM_NvmWriteBlock(RRAMC0, address, (uint8_t *)data);
643         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
644         }
645         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
646         {
647             /* Not supported for OTP */
648             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
649         }
650         else
651         {
652             /* Not supported type of NVM */
653             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
654         }
655     }
656     return status;
657 }
658 
cyhal_nvm_otp_write(cyhal_nvm_t * obj,uint32_t address,uint8_t data)659 cy_rslt_t cyhal_nvm_otp_write(cyhal_nvm_t* obj, uint32_t address, uint8_t data)
660 {
661     CY_ASSERT(NULL != obj);
662     CY_UNUSED_PARAMETER(obj);
663 
664     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
665     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
666 
667     bool is_address_valid = false;
668     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
669 
670     if (!is_address_valid)
671     {
672         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
673     }
674     else
675     {
676         if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
677         {
678         #if (_CYHAL_DRIVER_AVAILABLE_NVM_OTP)
679             status = (cy_rslt_t)Cy_RRAM_OtpWriteByteArray(RRAMC0, address, (const uint8_t *)&data, 1UL);
680         #endif /* (_CYHAL_DRIVER_AVAILABLE_NVM_OTP) */
681         }
682         else
683         {
684             /* Not supported type of NVM */
685             CY_UNUSED_PARAMETER(data);
686             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
687         }
688     }
689     return status;
690 }
691 
cyhal_nvm_program(cyhal_nvm_t * obj,uint32_t address,const uint32_t * data)692 cy_rslt_t cyhal_nvm_program(cyhal_nvm_t *obj, uint32_t address, const uint32_t *data)
693 {
694     CY_ASSERT(NULL != obj);
695     CY_UNUSED_PARAMETER(obj);
696 
697     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
698     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
699 
700     bool is_address_valid = false;
701     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
702 
703     if (!is_address_valid)
704     {
705         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
706     }
707     else
708     {
709         #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
710         SCB_CleanDCache_by_Addr((void *)data, _cyhal_nvm_current_block_info.block_size);
711         SCB_InvalidateDCache_by_Addr((void *)address, _cyhal_nvm_current_block_info.block_size);
712         #endif
713         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
714         {
715         #if (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH)) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
716             status = _cyhal_flash_run_operation(Cy_Flash_ProgramRow, address, data, true);
717         #endif /* (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH)) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
718         }
719         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
720         {
721         #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
722             status = (cy_rslt_t)Cy_RRAM_NvmWriteBlock(RRAMC0, address, (uint8_t *)data);
723         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
724         }
725         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
726         {
727             /* Not supported for OTP */
728             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
729         }
730         else
731         {
732             /* Not supported type of NVM */
733             CY_UNUSED_PARAMETER(address);
734             CY_UNUSED_PARAMETER(data);
735             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
736         }
737     }
738     return status;
739 }
740 
cyhal_nvm_start_erase(cyhal_nvm_t * obj,uint32_t address)741 cy_rslt_t cyhal_nvm_start_erase(cyhal_nvm_t *obj, uint32_t address)
742 {
743     CY_ASSERT(NULL != obj);
744     CY_UNUSED_PARAMETER(obj);
745 
746     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
747     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
748 
749     bool is_address_valid = false;
750     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
751 
752     if (!is_address_valid)
753     {
754         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
755     }
756     else
757     {
758         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
759         {
760         #if defined(CY_IP_MXS40SRSS) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
761             if (_cyhal_flash_pending_pm_change)
762             {
763                 status = CYHAL_SYSPM_RSLT_ERR_PM_PENDING;
764             }
765             else
766             {
767                 status = (cy_rslt_t)_cyhal_flash_convert_status(
768             #if _CYHAL_USES_ECT_FLASH
769                     Cy_Flash_StartEraseSector(address)
770             #else
771                     Cy_Flash_StartEraseRow(address)
772             #endif
773                     );
774             }
775         #endif /* defined(CY_IP_MXS40SRSS) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
776         }
777         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
778         {
779             /* Erase operation not needed for RRAM */
780             status = CY_RSLT_SUCCESS;
781         }
782         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
783         {
784             /* Not supported for OTP */
785             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
786         }
787         else
788         {
789             /* Not supported type of NVM */
790             CY_UNUSED_PARAMETER(address);
791             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
792         }
793     }
794     return status;
795 }
796 
cyhal_nvm_start_write(cyhal_nvm_t * obj,uint32_t address,const uint32_t * data)797 cy_rslt_t cyhal_nvm_start_write(cyhal_nvm_t *obj, uint32_t address, const uint32_t* data)
798 {
799     CY_ASSERT(NULL != obj);
800     CY_UNUSED_PARAMETER(obj);
801 
802     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
803     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
804 
805     bool is_address_valid = false;
806     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
807 
808     if (!is_address_valid)
809     {
810         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
811     }
812     else
813     {
814         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
815         {
816             /* M7CPUSS does not support write, only erase + program */
817         #if ((defined(CY_IP_MXS40SRSS) && !(_CYHAL_USES_ECT_FLASH)) || CY_FLASH_NON_BLOCKING_SUPPORTED) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
818             status = _cyhal_flash_run_operation(Cy_Flash_StartWrite, address, data, false);
819         #else
820             CY_UNUSED_PARAMETER(address);
821             CY_UNUSED_PARAMETER(data);
822             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
823         #endif /* ((defined(CY_IP_MXS40SRSS) && !(_CYHAL_USES_ECT_FLASH)) || CY_FLASH_NON_BLOCKING_SUPPORTED) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)*/
824         }
825         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
826         {
827         #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
828             status = (cy_rslt_t)Cy_RRAM_NonBlockingNvmWriteByteArray(
829                         RRAMC0, address, (const uint8_t *)data, _cyhal_nvm_current_block_info.block_size);
830         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
831         }
832         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
833         {
834             /* Not supported for OTP */
835             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
836         }
837         else
838         {
839             /* Not supported type of NVM */
840             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
841         }
842     }
843     return status;
844 }
845 
cyhal_nvm_start_program(cyhal_nvm_t * obj,uint32_t address,const uint32_t * data)846 cy_rslt_t cyhal_nvm_start_program(cyhal_nvm_t *obj, uint32_t address, const uint32_t* data)
847 {
848     CY_ASSERT(NULL != obj);
849     CY_UNUSED_PARAMETER(obj);
850 
851     cyhal_nvm_region_info_t _cyhal_nvm_current_block_info;
852     cy_rslt_t status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
853 
854     bool is_address_valid = false;
855     is_address_valid = _cyhal_nvm_get_nvm_region_by_address(address, &_cyhal_nvm_current_block_info);
856 
857     if (!is_address_valid)
858     {
859         status = CYHAL_NVM_RSLT_ERR_ADDRESS;
860     }
861     else
862     {
863         if (CYHAL_NVM_TYPE_FLASH == _cyhal_nvm_current_block_info.nvm_type)
864         {
865         #if defined(CY_IP_MXS40SRSS) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
866             #if _CYHAL_USES_ECT_FLASH /* StartWrite on this device behaves the same as StartProgram on others */
867                 status = _cyhal_flash_run_operation(Cy_Flash_StartWrite, address, data, false);
868             #else
869                 status = _cyhal_flash_run_operation(Cy_Flash_StartProgram, address, data, false);
870             #endif
871         #else
872             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
873         #endif /* defined(CY_IP_MXS40SRSS) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)*/
874         }
875         else if (CYHAL_NVM_TYPE_RRAM == _cyhal_nvm_current_block_info.nvm_type)
876         {
877         #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
878             status = (cy_rslt_t)Cy_RRAM_NonBlockingNvmWriteByteArray(
879                         RRAMC0, address, (const uint8_t *)data, _cyhal_nvm_current_block_info.block_size);
880         #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
881         }
882         else if (CYHAL_NVM_TYPE_OTP == _cyhal_nvm_current_block_info.nvm_type)
883         {
884             /* Not supported for OTP */
885             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
886         }
887         else
888         {
889             /* Not supported type of NVM */
890             CY_UNUSED_PARAMETER(address);
891             CY_UNUSED_PARAMETER(data);
892             status = CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED;
893         }
894     }
895     return status;
896 }
897 
cyhal_nvm_is_operation_complete(cyhal_nvm_t * obj)898 bool cyhal_nvm_is_operation_complete(cyhal_nvm_t *obj)
899 {
900     CY_ASSERT(NULL != obj);
901     CY_UNUSED_PARAMETER(obj);
902 
903     bool complete = true;
904 
905 #if (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH) || CY_FLASH_NON_BLOCKING_SUPPORTED) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH)
906     complete = (CY_FLASH_DRV_SUCCESS == Cy_Flash_IsOperationComplete());
907     #if !defined(CY_IP_M7CPUSS) /* PDL automatically clears cache when necessary in M7 devices */
908         if (complete)
909             Cy_SysLib_ClearFlashCacheAndBuffer();
910     #endif
911 #else
912     complete = true;
913 #endif /* (defined(CY_IP_MXS40SRSS) || (_CYHAL_USES_ECT_FLASH) || CY_FLASH_NON_BLOCKING_SUPPORTED) && (_CYHAL_DRIVER_AVAILABLE_NVM_FLASH) */
914 
915 #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM)
916     if (complete)
917     {
918         complete = !_cyhal_rram_is_busy();
919     }
920 #endif /* #if (_CYHAL_DRIVER_AVAILABLE_NVM_RRAM) */
921 
922     return complete;
923 }
924 
925 /*
926 *  BWC for Flash HAL
927 *  DO NOT USE IN THE NEW DESIGN
928 */
929 
930 #if (CYHAL_DRIVER_AVAILABLE_FLASH)
931 static cyhal_flash_block_info_t _flash_blocks[_CYHAL_INTERNAL_FLASH_MEMORY_BLOCKS] = {0};
932 
cyhal_flash_get_info(const cyhal_flash_t * obj,cyhal_flash_info_t * info)933 void cyhal_flash_get_info(const cyhal_flash_t *obj, cyhal_flash_info_t *info)
934 {
935     CY_UNUSED_PARAMETER(obj);
936 
937     cyhal_nvm_info_t nvm_info;
938     uint32_t flash_region_count = 0;
939 
940     nvm_info.region_count = _CYHAL_NVM_MEMORY_BLOCKS_COUNT;
941     nvm_info.regions = &_cyhal_nvm_mem_regions[0];
942 
943     for (uint32_t i = 0; i < nvm_info.region_count; i++)
944     {
945         if (CYHAL_NVM_TYPE_FLASH == nvm_info.regions[i].nvm_type)
946         {
947             _flash_blocks[flash_region_count].start_address = nvm_info.regions[i].start_address;
948             _flash_blocks[flash_region_count].size = nvm_info.regions[i].size;
949             _flash_blocks[flash_region_count].sector_size = nvm_info.regions[i].sector_size;
950             _flash_blocks[flash_region_count].page_size = nvm_info.regions[i].block_size;
951             _flash_blocks[flash_region_count].erase_value = nvm_info.regions[i].erase_value;
952             flash_region_count++;
953         }
954     }
955     info->block_count = flash_region_count;
956     info->blocks = &_flash_blocks[0];
957 }
958 
959 #endif /* (CYHAL_DRIVER_AVAILABLE_FLASH) */
960 
961 
962 #if defined(__cplusplus)
963 }
964 #endif /* __cplusplus */
965 
966 #endif /* (CYHAL_DRIVER_AVAILABLE_NVM) */
967