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