1 /***************************************************************************//**
2 * \file cyhal_nvm.h
3 *
4 * \brief
5 * Provides a high level interface for interacting with the Infineon onboard
6 * NVM(Non-Volatile Memory).
7 * This interface abstracts out the chip specific details. If any chip specific
8 * functionality is necessary, or performance is critical the low level functions
9 * can be used directly.
10 *
11 ********************************************************************************
12 * \copyright
13 * Copyright 2018-2022 Cypress Semiconductor Corporation (an Infineon company) or
14 * an affiliate of Cypress Semiconductor Corporation
15 *
16 * SPDX-License-Identifier: Apache-2.0
17 *
18 * Licensed under the Apache License, Version 2.0 (the "License");
19 * you may not use this file except in compliance with the License.
20 * You may obtain a copy of the License at
21 *
22 *     http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Unless required by applicable law or agreed to in writing, software
25 * distributed under the License is distributed on an "AS IS" BASIS,
26 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 * See the License for the specific language governing permissions and
28 * limitations under the License.
29 *******************************************************************************/
30 
31 /**
32 * \addtogroup group_hal_nvm NVM (Onboard Non-Volatile Memory)
33 * \ingroup group_hal
34 * \{
35 * High level interface to the onboard Non-Volatile memory (Internal Flash, RRAM, OTP region).
36 *
37 * Onboard NVM provides non-volatile storage for factory settings, secure data,
38 * user firmware, configuration, and bulk data.
39 *
40 * This driver allows data to be read from and written to NVM. It also provides the
41 * ability to obtain information about the address and characteristics of the NVM
42 * block(s) contained on the device. During NVM write time, the device should not be
43 * reset (including XRES pin, software reset, and watchdog) or unexpected changes may
44 * be made to portions of the NVM. Also, the low-voltage detect circuits should be
45 * configured to generate an interrupt instead of a reset.
46 *
47 * \note A Read while Write violation may occur for some devices when a NVM Read
48 * operation is initiated in the same or neighboring NVM sector/region where the NVM
49 * Write, Erase(if applicable), or Program operation is working. Refer the device datasheet
50 * for more information. This violation may cause a HardFault exception. To avoid the
51 * Read while Write violation, the user must carefully split the Read and Write
52 * operations on NVM sectors/regions which are not neighboring, considering all cores in
53 * a multi-processor device. User may edit the linker script to place the code into
54 * neighboring sectors/regions. For example, use sectors number 0 and 1 for code and sectors
55 * 2 and 3 for data storage.
56 *
57 * \section hal_nvm_features Features
58 * * NVM operations are performed on a per-block (program) or per-sector (erase if applicable) basis
59 *   (Refer the device datasheet for more information on the block size)
60 * * Supports Blocking or Non-Blocking erase(if applicable), program, and write
61 * \section hal_nvm_code_snippet Code Snippets
62 * \subsection subsection_nvm_use_case_1 Snippet 1: Get NVM Characteristics
63 * Following code snippet demonstrates how to fetch NVM characteristics. Refer \ref
64 * cyhal_nvm_info_t for more information.
65 * \snippet hal_nvm.c snippet_cyhal_nvm_get_nvm_info
66 *
67 * \subsection subsection_nvm_use_case_2 Snippet 2: Blocking NVM Erase-Write and Read
68 * Following code snippet demonstrates blocking NVM write.
69 * It uses a constant array with a size equaling the size of one NVM row/block.
70 * It uses blocking NVM write operation which blocks the caller until the write is
71 * completed. It then verifies the NVM data by comparing the NVM data with the
72 * written data.
73 * \snippet hal_nvm.c snippet_cyhal_nvm_blocking_mode_nvmwrite
74 *
75 * \subsection subsection_nvm_use_case_3 Snippet 3: Non-blocking NVM Erase-Write and Read
76 * Following code snippet implements the non-blocking NVM write using polling to
77 * complete the NVM write operation. It uses a constant array with a size equaling
78 * the size of one NVM row/block. It uses a polling method to complete the NVM
79 * write operation. It then verifies the NVM data by comparing the NVM data with
80 * the written data.
81 * \snippet hal_nvm.c snippet_cyhal_nvm_non_blocking_mode_polling_nvmwrite
82 */
83 
84 #pragma once
85 
86 #include <stdint.h>
87 #include <stdbool.h>
88 #include <stddef.h>
89 #include "cyhal_general_types.h"
90 #include "cyhal_hw_types.h"
91 
92 #if defined(__cplusplus)
93 extern "C" {
94 #endif
95 
96 /*******************************************************************************
97 *       Defines
98 *******************************************************************************/
99 
100 /** \addtogroup group_hal_results_nvm NVM HAL Results
101  *  NVM specific return codes
102  *  \ingroup group_hal_results
103  *  \{ *//**
104  */
105 /** Invalid argument */
106 #define CYHAL_NVM_RSLT_ERR_ADDRESS                    \
107     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_NVM, 0))
108 /** API is not supported */
109 #define CYHAL_NVM_RSLT_ERR_NOT_SUPPORTED              \
110     (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_ABSTRACTION_HAL, CYHAL_RSLT_MODULE_NVM, 1))
111 /** Unable to support due to power state */
112 
113 /**
114  * \}
115  */
116 
117 /** Enum of Non-volatile memory (NVM) types */
118 typedef enum
119 {
120     CYHAL_NVM_TYPE_INVALID = 0U,  //!< Invalid type of NVM
121 	CYHAL_NVM_TYPE_FLASH   = 1U,  //!< Internal Flash
122 	CYHAL_NVM_TYPE_RRAM    = 2U,  //!< RRAM
123 	CYHAL_NVM_TYPE_OTP     = 3U   //!< OTP
124 } cyhal_nvm_type_t;
125 
126 /** @brief Information about a single region of NVM memory */
127 typedef struct
128 {
129 	cyhal_nvm_type_t    nvm_type;              //!< NVM type.
130 	uint32_t            start_address;         //!< Base address of the distinct NVM region.
131 	uint32_t            offset;                //!< Offset to the address in the distinct NVM region.
132 	uint32_t            size;                  //!< Size of the distinct NVM region.
133 	uint32_t            sector_size;           //!< Sector size of the distinct NVM region.
134     uint32_t            block_size;            //!< Block size (programming granularity) of the distinct NVM region.
135 	bool                is_erase_required;     //!< true = erase required before program, false = erase not required before program.
136 	uint8_t             erase_value;           //!< NVM erase value (if applicable).
137 } cyhal_nvm_region_info_t;
138 
139 /** @brief Information about all of the regions of NVM memory */
140 typedef struct
141 {
142     uint8_t region_count;                     //!< The number of distinct NVM regions.
143     const cyhal_nvm_region_info_t* regions;   //!< Array of the distinct NVM regions.
144 } cyhal_nvm_info_t;
145 
146 
147 /*******************************************************************************
148 *       Functions
149 *******************************************************************************/
150 
151 /** Initialize the \ref cyhal_nvm_t object for accessing NVM through the HAL.
152  *
153  * @param[in] obj Pointer to a NVM object. The caller must allocate the memory
154  * for this object but the init function will initialize its contents.
155  * @return The status of the init request. Returns \ref CY_RSLT_SUCCESS on successful operation.
156  */
157 cy_rslt_t cyhal_nvm_init(cyhal_nvm_t* obj);
158 
159 /** Free resources associated with the NVM HAL driver.
160  *
161  * @param[out] obj The NVM object.
162  *
163  */
164 void cyhal_nvm_free(cyhal_nvm_t* obj);
165 
166 /** Get details about the NVM memory regions such as NVM type, start address, size, is_erase_required, and erase values etc.
167  * Refer \ref cyhal_nvm_info_t, cyhal_nvm_region_info_t for more information.
168  *
169  * @param[in]  obj  The NVM object.
170  * @param[out] info The NVM characteristic info.
171  *
172  * Refer \ref subsection_nvm_use_case_1 for more information.
173  */
174 void cyhal_nvm_get_info(cyhal_nvm_t* obj, cyhal_nvm_info_t* info);
175 
176 /** Read size amount of data starting from the given address of NVM.
177  *
178  * @param[in]  obj     The NVM object.
179  * @param[in]  address Address to begin reading from.
180  * @param[out] data    The buffer to read data into.
181  * @param[in]  size    The number of bytes to read.
182  * @return The status of the read request. Returns \ref CY_RSLT_SUCCESS on successful operation.
183  *
184  * Refer \ref subsection_nvm_use_case_2 for more information.
185  *
186  */
187 cy_rslt_t cyhal_nvm_read(cyhal_nvm_t* obj, uint32_t address, uint8_t* data, size_t size);
188 
189 /** Erase one block of NVM starting at the given address. The address must be at block boundary.
190  * This will block until the erase operation is complete.
191  *
192  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values, is erase
193  * required/applicable, and the erase block size(if applicable).
194  *
195  * @param[in] obj The NVM object
196  * @param[in] address The block address to be erased
197  * @return The status of the erase request. Returns \ref CY_RSLT_SUCCESS on successful operation.
198  *
199  * Refer \ref subsection_nvm_use_case_2 for more information.
200  */
201 cy_rslt_t cyhal_nvm_erase(cyhal_nvm_t* obj, uint32_t address);
202 
203 /** This function erases the block, if required, and writes the new data into the block starting
204  * at the given address. The address must be at block boundary. This will block until the write
205  * operation is complete.
206  *
207  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values and
208  * the write block size. The provided data buffer must be at least as large as the NVM
209  * block_size.
210  * @note Generally the \p data to be written must be located in the SRAM memory region.
211  *
212  * @param[in] obj The NVM object
213  * @param[in] address The address of the block to be written
214  * @param[in] data The data buffer to be written to the NVM block
215  * @return The status of the write request. Returns \ref CY_RSLT_SUCCESS on successful operation.
216  *
217  * Refer \ref subsection_nvm_use_case_2 for more information.
218  */
219 cy_rslt_t cyhal_nvm_write(cyhal_nvm_t* obj, uint32_t address, const uint32_t* data);
220 
221 /** Write one-time data to the given byte location in the provided block of NVM OTP region. The block
222  * must be within the defined block range of the OTP (refer the device datasheet for more information).
223  *
224  * @note You can only ONCE write data at desired byte in specific block,
225  * if you will try to do it more times, you can have broken data at this location.
226  * @see cyhal_nvm_get_info() to get the NVM OTP region characteristics for legal address values, size
227  * and the OTP block size.
228  *
229  * @param[in] obj The NVM object
230  * @param[in] address The address of the block to be written
231  * @param[in] data The data to be written to the OTP memory
232  * @return The status of the program request. Returns \ref CY_RSLT_SUCCESS on successful operation.
233  */
234 cy_rslt_t cyhal_nvm_otp_write(cyhal_nvm_t* obj, uint32_t address, uint8_t data);
235 
236 /** Program one block with the provided data starting at the given address. The address must be
237  * at block boundary. This will block until the write operation is complete.
238  *
239  * @note This function does not erase the block prior to writing. The block must be erased
240  * first via a separate call to erase.
241  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values and
242  * the total block size. The provided data buffer must be at least as large as the NVM
243  * block_size.
244  * @note Generally the \p data to be programmed must be located in the SRAM memory region.
245  *
246  * @param[in] obj The NVM object
247  * @param[in] address The address of the block to be programmed
248  * @param[in] data The data buffer to be programmed to the NVM block
249  * @return The status of the program request. Returns \ref CY_RSLT_SUCCESS on successful operation.
250  */
251 cy_rslt_t cyhal_nvm_program(cyhal_nvm_t* obj, uint32_t address, const uint32_t* data);
252 
253 /** Start an asynchronous erase of a single block of NVM starting at the given address.
254  * Returns immediately and reports a successful start or reason for failure. The address must
255  * be aligned on a block boundary.
256  *
257  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values, is erase
258  * required/applicable, and the erase block size(if applicable).
259  *
260  * @param[in] obj The NVM object
261  * @param[in] address The block address to be erased
262  * @return The status of the start_erase request.
263  *
264  * Refer \ref subsection_nvm_use_case_3 for more information.
265  */
266 cy_rslt_t cyhal_nvm_start_erase(cyhal_nvm_t* obj, uint32_t address);
267 
268 /** Start an asynchronous write (Erase if required + Program) on single block of NVM starting at the
269  * given address.
270  * Returns immediately and reports a successful start or reason for failure. The address must be
271  * aligned on a block boundary.
272  *
273  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values and
274  * the write block size. The provided data buffer must be at least as large as the NVM
275  * block_size.
276  * @note Generally the \p data to be written must be located in the SRAM memory region.
277  *
278  * @param[in] obj The NVM object
279  * @param[in] address The address of the block to be written
280  * @param[in] data The data buffer to be written to the NVM block
281  * @return The status of the start_write request.
282  *
283  * Refer \ref subsection_nvm_use_case_3 for more information.
284  */
285 cy_rslt_t cyhal_nvm_start_write(cyhal_nvm_t* obj, uint32_t address, const uint32_t* data);
286 
287 
288 /** Start asynchronous programming of a single block of NVM starting at the given address.
289  * Returns immediately and reports a successful start or reason for failure.
290  *
291  * \note This function does not erase the block prior to writing. The block must be erased
292  * first via a separate call to erase.
293  *
294  * @see cyhal_nvm_get_info() to get the NVM characteristics for legal address values and
295  * the total block size. The provided data buffer must be at least as large as the NVM
296  * block_size.
297  * @note Generally the \p data to be programmed must be located in the SRAM memory region.
298  *
299  * @param[in] obj The NVM object
300  * @param[in] address The address of the block to be programmed
301  * @param[in] data The data buffer to be programmed to the NVM block
302  * @return The status of the program request. Returns \ref CY_RSLT_SUCCESS on successful operation.
303  */
304 cy_rslt_t cyhal_nvm_start_program(cyhal_nvm_t *obj, uint32_t address, const uint32_t* data);
305 
306 /** Reports status of the last NVM operation.
307  *
308  * @param[in] obj The NVM object
309  * @return true if NVM operation is complete. false otherwise.
310  */
311 bool cyhal_nvm_is_operation_complete(cyhal_nvm_t *obj);
312 
313 
314 #if defined(__cplusplus)
315 }
316 #endif
317 
318 #ifdef CYHAL_NVM_IMPL_HEADER
319 #include CYHAL_NVM_IMPL_HEADER
320 #endif /* CYHAL_NVM_IMPL_HEADER */
321 
322 /** \} group_hal_nvm */
323