1 /***********************************************************************************************************************
2 * Copyright [2015-2017] Renesas Electronics Corporation and/or its licensors. All Rights Reserved.
3 *
4 * This file is part of Renesas SynergyTM Software Package (SSP)
5 *
6 * The contents of this file (the "contents") are proprietary and confidential to Renesas Electronics Corporation
7 * and/or its licensors ("Renesas") and subject to statutory and contractual protections.
8 *
9 * This file is subject to a Renesas SSP license agreement. Unless otherwise agreed in an SSP license agreement with
10 * Renesas: 1) you may not use, copy, modify, distribute, display, or perform the contents; 2) you may not use any name
11 * or mark of Renesas for advertising or publicity purposes or in connection with your use of the contents; 3) RENESAS
12 * MAKES NO WARRANTY OR REPRESENTATIONS ABOUT THE SUITABILITY OF THE CONTENTS FOR ANY PURPOSE; THE CONTENTS ARE PROVIDED
13 * "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, AND NON-INFRINGEMENT; AND 4) RENESAS SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, OR
15 * CONSEQUENTIAL DAMAGES, INCLUDING DAMAGES RESULTING FROM LOSS OF USE, DATA, OR PROJECTS, WHETHER IN AN ACTION OF
16 * CONTRACT OR TORT, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE CONTENTS. Third-party contents
17 * included in this file may be subject to different terms.
18 **********************************************************************************************************************/
19
20 /**********************************************************************************************************************
21 * File Name : r_flash_lp.c
22 * Description : HLD Interface for the Low power FLASH peripheral on SC32 MCUs.
23 **********************************************************************************************************************/
24
25
26 /***********************************************************************************************************************
27 * Includes
28 **********************************************************************************************************************/
29 #include "bsp_api.h"
30
31 #include "r_flash_lp.h"
32 #include "hw/target/hw_flash_lp_private.h"
33 #include "r_flash_lp_private_api.h"
34 /* Configuration for this package. */
35 #include "r_flash_cfg.h"
36 #include "r_cgc_api.h"
37 #include "r_cgc.h"
38 #include "hw/target/flash_lp_core/hw_dataflash.h"
39 #include "hw/target/flash_lp_core/hw_codeflash_extra.h"
40 #include "hw/target/flash_lp_core/hw_codeflash.h"
41
42 /***********************************************************************************************************************
43 * Typedef definitions
44 **********************************************************************************************************************/
45 /** "OPEN" in ASCII, used to avoid multiple open. */
46 #define FLASH_OPEN (0x4f50454eULL)
47 #define FLASH_CLOSE (0U)
48
49 #define MINIMUM_SUPPORTED_FCLK_FREQ 4000000U /// Minimum FCLK for Flash Operations in Hz
50
51 /***********************************************************************************************************************
52 * Macro definitions
53 **********************************************************************************************************************/
54 /** Macro for error logger. */
55 #ifndef FLASH_ERROR_RETURN
56 /*LDRA_INSPECTED 77 S This macro does not work when surrounded by parentheses. */
57 #define FLASH_ERROR_RETURN(a, err) SSP_ERROR_RETURN((a), (err), &g_module_name[0], &g_flash_lp_version)
58 #endif
59
60 /***********************************************************************************************************************
61 * Private function prototypes
62 **********************************************************************************************************************/
63
64 /***********************************************************************************************************************
65 * Private global variables
66 **********************************************************************************************************************/
67 static flash_block_info_t g_block_info = {0U}; /// Structure holding block info about an address.
68 static bsp_lock_t g_flash_Lock = {0U}; /// Flash commands software lock
69
70 /** Structure that holds the parameters for current operations*/
71 static current_parameters_t g_current_parameters = {0U};
72
73 /** State variable for the Flash API. */
74 static flash_states_t g_flash_state = FLASH_STATE_UNINITIALIZED;
75
76 /** Internal functions. */
77 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
78 static ssp_err_t flash_lock_state (flash_states_t new_state) PLACE_IN_RAM_SECTION;
79
80 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
81 static ssp_err_t setup_for_pe_mode (flash_lp_instance_ctrl_t * const p_ctrl, flash_type_t flash_type, flash_states_t flash_state) PLACE_IN_RAM_SECTION;
82
83 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
84 static ssp_err_t flash_setup (flash_lp_instance_ctrl_t * const p_ctrl) PLACE_IN_RAM_SECTION;
85
86 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
87 static ssp_err_t flash_open_setup (flash_lp_instance_ctrl_t * const p_ctrl, ssp_feature_t *p_ssp);
88
89 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
90 static ssp_err_t flash_blank_check_address_checking (uint32_t const address, uint32_t num_bytes) PLACE_IN_RAM_SECTION;
91
92 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
93 static ssp_err_t flash_blank_check_initiate ( flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const address, uint32_t num_bytes, flash_result_t *p_blank_check_result) PLACE_IN_RAM_SECTION;
94
95 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
96 static void flash_operation_complete (flash_lp_instance_ctrl_t * const p_ctrl, ssp_err_t err) PLACE_IN_RAM_SECTION;
97
98 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
99 static ssp_err_t flash_write_initiate (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const src_start_address, uint32_t dest_start_address, uint32_t num_bytes) PLACE_IN_RAM_SECTION;
100
101 static ssp_err_t flash_fmi_setup (flash_lp_instance_ctrl_t * const p_ctrl, flash_cfg_t const * const p_cfg, ssp_feature_t *p_ssp);
102
103 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
104 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
105 static ssp_err_t flash_write_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t flash_address, uint32_t const num_bytes) PLACE_IN_RAM_SECTION;
106
107 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
108 static ssp_err_t flash_erase_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const num_blocks) PLACE_IN_RAM_SECTION;
109
110 /*LDRA_INSPECTED 219 s - This is an allowed exception to LDRA standard 219 S "User name starts with underscore."*/
111 static ssp_err_t flash_blank_check_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const address, uint32_t num_bytes) PLACE_IN_RAM_SECTION;
112 #endif
113
114 /***********************************************************************************************************************
115 * Exported global variables
116 **********************************************************************************************************************/
117 /*LDRA_NOANALYSIS LDRA_INSPECTED below not working. */
118 /*LDRA_INSPECTED 27 D This structure must be accessible in user code. It cannot be static. */
119 const flash_api_t g_flash_on_flash_lp =
120 {
121 .open = R_FLASH_LP_Open,
122 .close = R_FLASH_LP_Close,
123 .write = R_FLASH_LP_Write,
124 .read = R_FLASH_LP_Read,
125 .erase = R_FLASH_LP_Erase,
126 .blankCheck = R_FLASH_LP_BlankCheck,
127 .statusGet = R_FLASH_LP_StatusGet,
128 .infoGet = R_FLASH_LP_InfoGet,
129 .accessWindowSet = R_FLASH_LP_AccessWindowSet,
130 .accessWindowClear = R_FLASH_LP_AccessWindowClear,
131 .idCodeSet = R_FLASH_LP_IdCodeSet,
132 .reset = R_FLASH_LP_Reset,
133 .startupAreaSelect = R_FLASH_LP_StartUpAreaSelect,
134 .updateFlashClockFreq = R_FLASH_LP_UpdateFlashClockFreq,
135 .versionGet = R_FLASH_LP_VersionGet
136 };
137 /*LDRA_ANALYSIS */
138 #if defined(__GNUC__)
139 /* This structure is affected by warnings from a GCC compiler bug. This pragma suppresses the warnings in this
140 * structure only.*/
141 /*LDRA_INSPECTED 69 S */
142 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
143 #endif
144 /** Version data structure used by error logger macro. */
145 static const ssp_version_t g_flash_lp_version =
146 {
147 .api_version_minor = FLASH_API_VERSION_MINOR,
148 .api_version_major = FLASH_API_VERSION_MAJOR,
149 .code_version_major = FLASH_LP_CODE_VERSION_MAJOR,
150 .code_version_minor = FLASH_LP_CODE_VERSION_MINOR
151 };
152 #if defined(__GNUC__)
153 /* Restore warning settings for 'missing-field-initializers' to as specified on command line. */
154 /*LDRA_INSPECTED 69 S */
155 #pragma GCC diagnostic pop
156 #endif
157
158 /** Name of module used by error logger macro */
159 #if BSP_CFG_ERROR_LOG != 0
160 static const char g_module_name[] = "r_flash_lp";
161 #endif
162
163 static flash_fmi_regions_t g_flash_code_region = {0U};
164 static flash_fmi_regions_t g_flash_data_region = {0U};
165
166 /***********************************************************************************************************************
167 * Functions
168 **********************************************************************************************************************/
169
170 /*******************************************************************************************************************//**
171 * @addtogroup FLASH
172 * @{
173 **********************************************************************************************************************/
174
175 /*******************************************************************************************************************//**
176 * @brief Initialize the Low Power flash peripheral. Implements flash_api_t::open.
177 *
178 * The Open function initializes the Flash. It first copies the FCU firmware to FCURAM
179 * and sets the FCU Clock based on the current FCLK frequency. In addition, if Code Flash programming is enabled,
180 * the API code responsible for Code Flash programming will be copied to RAM.
181 *
182 * This function must be called once prior to calling any other FLASH API functions.
183 * If a user supplied callback function is supplied, then the Flash Ready interrupt will be configured to
184 * call the users callback routine with an Event type describing the source of the interrupt for Data Flash
185 * operations.
186 * Subsequent to successfully completing this call p_ctrl->opened will be true.
187 *
188 * @note Providing a callback function in the supplied p_cfg->callback field, automatically configures the
189 * Flash for Data Flash to operate in non-blocking (BGO) mode.
190 *
191 * Subsequent to a successful Open(), the Flash is ready to process additional Flash commands.
192 *
193 * @retval SSP_SUCCESS Initialization was successful and timer has started.
194 * @retval SSP_FLASH_ERR_FAILURE Failed to successfully enter Programming/Erase mode.
195 * @retval SSP_ERR_TIMEOUT Timed out waiting for FCU to be ready.
196 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl or p_cfg or problem getting FMI info.
197 * @retval SSP_ERR_IRQ_BSP_DISABLED Caller is requesting BGO but the Flash interrupts are not enabled.
198 * @retval SSP_ERR_FCLK FCLK must be a minimum of 4 MHz for Flash operations.
199 * @retval SSP_ERR_IN_USE Flash Open() has already been called.
200 * @retval SSP_ERR_HW_LOCKED Flash module unable to get the Hardware lock for the Flash LP Periperhal.
201 * @return See @ref Common_Error_Codes or functions called by this function for other possible
202 * return codes. This function calls:
203 * * fmi_api_t::productFeatureGet
204 * * fmi_api_t::eventInfoGet
205 *
206 **********************************************************************************************************************/
R_FLASH_LP_Open(flash_ctrl_t * const p_api_ctrl,flash_cfg_t const * const p_cfg)207 ssp_err_t R_FLASH_LP_Open (flash_ctrl_t * const p_api_ctrl, flash_cfg_t const * const p_cfg)
208 {
209 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
210 ssp_feature_t ssp_feature = {{(ssp_ip_t) 0}};
211
212 /* g_flash_lp_version is accessed by the ASSERT macro only, and so compiler toolchain can issue a
213 * warning that it is not accessed. The code below eliminates this warning and also ensures data
214 * structures are not optimized away. */
215 SSP_PARAMETER_NOT_USED(g_flash_lp_version);
216
217 ssp_err_t err = SSP_SUCCESS;
218
219 /** If null pointers return error. */
220 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
221 SSP_ASSERT(NULL != p_cfg);
222 SSP_ASSERT(NULL != p_ctrl);
223 #endif
224
225 /** If open return error. */
226 FLASH_ERROR_RETURN((FLASH_OPEN != p_ctrl->opened), SSP_ERR_IN_USE);
227
228 /** Setup flash FMI. If failure return error. */
229 err = flash_fmi_setup(p_ctrl, p_cfg, &ssp_feature);
230 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
231
232 /** Allow Initialization if not initialized or if no operation is ongoing and re-initialization is desired */
233 if ((FLASH_STATE_UNINITIALIZED == g_flash_state) || (FLASH_STATE_READY == g_flash_state))
234 {
235 /** Acquire the software lock. If failure return error. */
236 FLASH_ERROR_RETURN(!(SSP_SUCCESS != flash_lock_state(FLASH_STATE_INITIALIZATION)), SSP_ERR_IN_USE);
237 }
238
239 /** Set the parameters struct based on the user supplied settings */
240 g_current_parameters.bgo_enabled_df = p_cfg->data_flash_bgo;
241
242 if (g_current_parameters.bgo_enabled_df == true)
243 {
244 /** Setup the Flash interrupt callback based on the caller's info. If the Flash interrupt is
245 * not enabled in the BSP then this will return SSP_ERR_IRQ_BSP_DISABLED */
246 err = HW_FLASH_LP_irq_cfg((bool) (p_cfg->p_callback != NULL), p_cfg, p_ctrl->irq);
247 }
248 else
249 {
250 /** Make sure Flash interrupts are disabled, they are only used in BGO mode */
251 HW_FLASH_LP_irq_cfg(false, p_cfg, p_ctrl->irq);
252 }
253
254 /** Setup the flash. */
255 err = flash_open_setup(p_ctrl, &ssp_feature);
256
257 /** Save callback function pointer */
258 p_ctrl->p_callback = p_cfg->p_callback;
259
260 return err;
261 }
262
263 /*******************************************************************************************************************//**
264 * @brief Write to the specified Code or Data Flash memory area. Implements flash_api_t::write.
265 *
266 * The minimum/maximum number of bytes, as well as the invalid address and programming boundaries supported and
267 * enforced by this function are dependent on the MCU in use as well as the part package size.
268 * Please see the User manual and/or requirements document for additional information.
269 *
270 * @retval SSP_SUCCESS Operation successful. If BGO is enabled this means the operation was started
271 * successfully.
272 * @retval SSP_ERR_IN_USE The Flash peripheral is busy with a prior on-going transaction.
273 * @retval SSP_ERR_NOT_OPEN The Flash API is not Open.
274 * @retval SSP_ERR_CMD_LOCKED FCU is in locked state, typically as a result of attempting to Write
275 * an area that is protected by an Access Window.
276 * @retval SSP_ERR_WRITE_FAILED Status is indicating a Programming error for the requested operation. This
277 * may be returned if the requested Flash area is not blank.
278 * @retval SSP_ERR_TIMEOUT Timed out waiting for FCU operation to complete.
279 * @retval SSP_ERR_INVALID_SIZE Number of bytes provided was not a multiple of the programming size or exceeded
280 * the maximum range.
281 * @retval SSP_ERR_INVALID_ADDRESS Invalid address was input or address not on programming boundary.
282 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl.
283 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled and a request to write CF was requested.
284 **********************************************************************************************************************/
R_FLASH_LP_Write(flash_ctrl_t * const p_api_ctrl,uint32_t const src_address,uint32_t flash_address,uint32_t const num_bytes)285 ssp_err_t R_FLASH_LP_Write (flash_ctrl_t * const p_api_ctrl,
286 uint32_t const src_address,
287 uint32_t flash_address,
288 uint32_t const num_bytes)
289 {
290 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
291 ssp_err_t err = SSP_SUCCESS;
292
293 /** Get the block information for this address. If failure return error. */
294 FLASH_ERROR_RETURN((flash_get_block_info(flash_address, &g_block_info)), SSP_ERR_INVALID_ADDRESS);
295
296 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
297 /** Check parameters. If failure return error */
298 err = flash_write_parameter_checking (p_ctrl, flash_address, num_bytes);
299 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
300
301 /** If control block is not open return error. */
302 FLASH_ERROR_RETURN((FLASH_OPEN == p_ctrl->opened), SSP_ERR_NOT_OPEN);
303 #endif /* if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1) */
304
305 /** Initiate the write operation. */
306 err = flash_write_initiate(p_ctrl, src_address, flash_address, num_bytes);
307
308 /* Complete the flash operation. */
309 flash_operation_complete (p_ctrl, err);
310
311 /** Return status. */
312 return err;
313 }
314
315 /*******************************************************************************************************************//**
316 * @brief Read the requested number of bytes from the supplied Data or Code Flash address. Implements flash_api_t::read.
317 *
318 * The minimum/maximum number of blocks, as well as the invalid address and programming boundaries supported and
319 * enforced by this function are dependent on the MCU in use as well as the part package size.
320 * Please see the User manual and/or requirements document for additional information.
321 * @note This function is provided simply for the purposes of maintaining a complete interface.
322 * It is possible (and recommended), to read Flash memory directly.
323 *
324 * @retval SSP_SUCCESS Operation successful.
325 * @retval SSP_ERR_INVALID_ADDRESS Invalid Flash address was supplied.
326 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl or p_dest_address
327 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
328 **********************************************************************************************************************/
R_FLASH_LP_Read(flash_ctrl_t * const p_api_ctrl,uint8_t * p_dest_address,uint32_t const flash_address,uint32_t const num_bytes)329 ssp_err_t R_FLASH_LP_Read (flash_ctrl_t * const p_api_ctrl, uint8_t * p_dest_address, uint32_t const flash_address,
330 uint32_t const num_bytes)
331 {
332 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
333
334 /* Eliminate warning if parameter checking is disabled. */
335 SSP_PARAMETER_NOT_USED(p_ctrl);
336
337 ssp_err_t err = SSP_SUCCESS;
338 uint32_t index;
339 uint8_t * p_flash_ptr = (uint8_t *) flash_address;
340
341 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
342 /** If null pointers return error */
343 SSP_ASSERT(NULL != p_dest_address);
344 SSP_ASSERT(NULL != p_ctrl);
345
346 /** If invalid number of bytes return error. */
347 FLASH_ERROR_RETURN((0 != num_bytes), SSP_ERR_INVALID_SIZE);
348
349 /** If not open return error */
350 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
351
352 /** Get the block information for this address. If failure return error. */
353 FLASH_ERROR_RETURN((flash_get_block_info(flash_address, &g_block_info)), SSP_ERR_INVALID_ADDRESS);
354
355 /** Insure the read request doesn't span across the end of the CF or DF range. If it does return error. */
356 FLASH_ERROR_RETURN(((flash_address + (num_bytes - 1U)) <= g_block_info.memory_end_addr), SSP_ERR_INVALID_ADDRESS);
357 #endif /* if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1) */
358
359 /** Copy the data to the destination buffer. */
360 for (index = (uint32_t)0; index < num_bytes; index++)
361 {
362 p_dest_address[index] = p_flash_ptr[index];
363 }
364
365 return err;
366 }
367
368 /*******************************************************************************************************************//**
369 * @brief Erase the specified Code or Data Flash blocks. Implements flash_api_t::erase.
370 *
371 * The minimum/maximum number of blocks, as well as the invalid address and programming boundaries supported and
372 * enforced by this function are dependent on the MCU in use as well as the part package size.
373 * Please see the User manual and/or requirements document for additional information.
374 * @retval SSP_SUCCESS Successful open.
375 * @retval SSP_ERR_INVALID_BLOCKS Invalid number of blocks specified
376 * @retval SSP_ERR_INVALID_ADDRESS Invalid address specified
377 * @retval SSP_ERR_IN_USE Other flash operation in progress, or API not initialized
378 * @retval SSP_ERR_CMD_LOCKED FCU is in locked state, typically as a result of attempting to Erase
379 * an area that is protected by an Access Window.
380 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
381 * @retval SSP_ERR_NOT_OPEN The Flash API is not Open.
382 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled and a request to erase CF was requested.
383 **********************************************************************************************************************/
R_FLASH_LP_Erase(flash_ctrl_t * const p_api_ctrl,uint32_t const address,uint32_t const num_blocks)384 ssp_err_t R_FLASH_LP_Erase (flash_ctrl_t * const p_api_ctrl, uint32_t const address, uint32_t const num_blocks)
385 {
386 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
387
388 ssp_err_t err = SSP_SUCCESS;
389
390 /** Get the block information for this address. If failure return error. */
391 FLASH_ERROR_RETURN((flash_get_block_info(address, &g_block_info)), SSP_ERR_INVALID_ADDRESS);
392
393 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
394 /** Verify erase parameters. If failure return error. */
395 err = flash_erase_parameter_checking (p_ctrl, num_blocks);
396 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
397 #endif /* if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1) */
398
399 /** Update Flash state and enter the respective Code or Data Flash P/E mode, may return SSP_ERR_IN_USE */
400 err = setup_for_pe_mode(p_ctrl, g_block_info.flash_type, FLASH_STATE_ERASING);
401
402 /** If successful */
403 if (SSP_SUCCESS == err)
404 {
405 /** Configure the current parameters based on if the operation is for code flash or data flash. */
406 if (g_block_info.is_code_flash_addr == true)
407 {
408 g_current_parameters.wait_cnt = g_current_parameters.wait_max_erase_cf_block;
409 g_current_parameters.current_operation = FLASH_OPERATION_CF_ERASE;
410 }
411 else
412 {
413 g_current_parameters.wait_cnt = g_current_parameters.wait_max_erase_df_block;
414 /** If this is a request to erase Data Flash configure BGO mode if it is enabled. */
415 if (g_current_parameters.bgo_enabled_df == false)
416 {
417 g_current_parameters.current_operation = FLASH_OPERATION_DF_ERASE;
418 }
419 else
420 {
421 g_current_parameters.current_operation = FLASH_OPERATION_DF_BGO_ERASE;
422 }
423 }
424
425 /** Initiate the flash erase. */
426 err = HW_FLASH_LP_erase(p_ctrl, g_block_info.this_block_st_addr, num_blocks, g_block_info.block_size);
427 if (SSP_SUCCESS == err)
428 {
429 /** If in non-BGO mode, the current operation is complete. Exit PE mode and return status*/
430 if (g_current_parameters.current_operation != FLASH_OPERATION_DF_BGO_ERASE)
431 {
432 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
433 }
434 }
435 }
436
437 /** Complete the flash operation. */
438 /* Execute a reset if any error, release the state if not BGO */
439 flash_operation_complete (p_ctrl, err);
440
441 return err;
442 }
443
444 /*******************************************************************************************************************//**
445 * @brief Perform a blank check on the specified address area. Implements flash_api_t::blankCheck.
446 *
447 * The minimum/maximum number of bytes, as well as the invalid address and programming boundaries supported and
448 * enforced by this function are dependent on the MCU in use as well as the part package size.
449 * Please see the User manual and/or requirements document for additional information.
450 * The number of bytes for Data Flash blank checking must be between (1 and FLASH_DATA_BLANK_CHECK_MAX).
451 * The number of bytes for Code Flash blank checking must be between (1 and FLASH_CODE_BLANK_CHECK_MAX).
452 *
453 * @retval SSP_SUCCESS Blankcheck operation completed with result in p_blank_check_result,
454 * or blankcheck started and in-progess (BGO mode).
455 * @retval SSP_ERR_INVALID_ADDRESS Invalid data flash address was input
456 * @retval SSP_ERR_INVALID_SIZE 'num_bytes' was either too large or not aligned for the CF/DF boundary size.
457 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
458 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
459 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
460 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled and a request to Blank Check CF was requested.
461 **********************************************************************************************************************/
R_FLASH_LP_BlankCheck(flash_ctrl_t * const p_api_ctrl,uint32_t const address,uint32_t num_bytes,flash_result_t * p_blank_check_result)462 ssp_err_t R_FLASH_LP_BlankCheck (flash_ctrl_t * const p_api_ctrl, uint32_t const address, uint32_t num_bytes,
463 flash_result_t * p_blank_check_result)
464 {
465 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
466 ssp_err_t err = SSP_SUCCESS;
467
468
469 /** Get the block information for this address. If failure return error. */
470 FLASH_ERROR_RETURN((flash_get_block_info(address, &g_block_info)), SSP_ERR_INVALID_ADDRESS);
471
472 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
473 err = flash_blank_check_parameter_checking (p_ctrl, address, num_bytes);
474 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
475 #endif /* if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1) */
476
477
478 /** Update Flash state and enter the respective Code or Data Flash P/E mode, may return SSP_ERR_IN_USE */
479 err = setup_for_pe_mode(p_ctrl, g_block_info.flash_type, FLASH_STATE_BLANK_CHECK);
480 if (SSP_SUCCESS == err)
481 {
482 /** Initiate the Blank Check operation */
483 err = flash_blank_check_initiate(p_ctrl, address, num_bytes, p_blank_check_result);
484 }
485
486 /** If failure reset the flash. */
487 /* SSP_ERR_IN_USE would indicate that a BGO operation is underway, so don't reset in that case */
488 if ((SSP_SUCCESS != err) && (SSP_ERR_IN_USE != err))
489 {
490 /* This will clear error flags and exit the P/E mode*/
491 HW_FLASH_LP_reset(p_ctrl);
492 }
493
494 /** If the current operation is not a BGO blank check release the flash. */
495 if (g_current_parameters.current_operation != FLASH_OPERATION_DF_BGO_BLANKCHECK)
496 {
497 flash_ReleaseState();
498 }
499
500 return err;
501 }
502
503 /*******************************************************************************************************************//**
504 * @brief Query the FLASH for its status. Implements flash_api_t::statusGet.
505 *
506 * @retval SSP_SUCCESS Flash is ready and available to accept commands.
507 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
508 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
509 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
510 **********************************************************************************************************************/
R_FLASH_LP_StatusGet(flash_ctrl_t * const p_api_ctrl)511 ssp_err_t R_FLASH_LP_StatusGet (flash_ctrl_t * const p_api_ctrl)
512 {
513 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
514
515 /* Eliminate warning if parameter checking is disabled. */
516 SSP_PARAMETER_NOT_USED(p_ctrl);
517
518 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
519 /** If null pointer return error. */
520 SSP_ASSERT(NULL != p_ctrl);
521
522 /** If not opern return error. */
523 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
524 #endif
525
526 /** Return flash status */
527 if (g_flash_state == FLASH_STATE_READY)
528 {
529 return SSP_SUCCESS;
530 }
531 else
532 {
533 return SSP_ERR_IN_USE;
534 }
535
536 }
537
538 /*******************************************************************************************************************//**
539 * @brief Configure an access window for the Code Flash memory. Implements flash_api_t::accessWindowSet.
540 *
541 * An access window defines a contiguous area in Code Flash for which programming/erase is enabled.
542 * This area is on block boundaries.
543 * The block containing start_addr is the first block. The block containing end_addr is the last block.
544 * The access window then becomes first block --> last block inclusive. Anything outside this range
545 * of Code Flash is then write protected.
546 * As an example, if you wanted to place an accesswindow on Code Flash Blocks 0 and 1, such that
547 * only those two blocks were writable, you would need to specify (address in block 0, address in block 2)
548 * as the respective start and end address.
549 * @note If the start address and end address are set to the same value, then the access window
550 * is effectively removed. This accomplishes the same functionality as R_FLASH_LP_AccessWindowClear().
551 *
552 * The invalid address and programming boundaries supported and enforced by this function are dependent on the MCU
553 * in use as well as the part package size. Please see the User manual and/or requirements document
554 * for additional information.
555 *
556 * @retval SSP_SUCCESS Access window successfully configured.
557 * @retval SSP_ERR_INVALID_ADDRESS Invalid settings for start_addr and/or end_addr.
558 * @retval SSP_ERR_IN_USE FLASH peripheral is busy with a prior operation.
559 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl.
560 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled.
561 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
562 **********************************************************************************************************************/
R_FLASH_LP_AccessWindowSet(flash_ctrl_t * const p_api_ctrl,uint32_t const start_addr,uint32_t const end_addr)563 ssp_err_t R_FLASH_LP_AccessWindowSet (flash_ctrl_t * const p_api_ctrl, uint32_t const start_addr,
564 uint32_t const end_addr)
565 {
566 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
567
568 /* Eliminate warning if parameter checking is disabled. */
569 SSP_PARAMETER_NOT_USED(p_ctrl);
570 SSP_PARAMETER_NOT_USED(start_addr); // Remove warnings generated when Code Flash code is not compiled in.
571 SSP_PARAMETER_NOT_USED(end_addr);
572
573 ssp_err_t err = SSP_SUCCESS;
574
575 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
576 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
577 /** If null pointer return error. */
578 SSP_ASSERT(NULL != p_ctrl);
579
580 /** If not open return error. */
581 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
582 #endif
583
584 uint32_t last_cf_block_index = g_flash_code_region.num_regions - 1U;
585 uint32_t cf_st_addr = g_flash_code_region.p_block_array[0].block_section_st_addr;
586 uint32_t cf_end_addr = g_flash_code_region.p_block_array[last_cf_block_index].block_section_end_addr;
587
588 /* Note that the end_addr indicates the address up to, but not including the block that contains that address. */
589 /* Therefore to allow the very last Block to be included in the access window we must allow for FLASH_CF_BLOCK_END+1 */
590 /** If the start or end addresses are invalid return error. */
591 if ((start_addr >= cf_st_addr) && (end_addr <= (cf_end_addr + 1)) && (start_addr <= end_addr))
592 {
593 /** Update Flash state and enter Code Flash P/E mode */
594 err = setup_for_pe_mode(p_ctrl, FLASH_TYPE_CODE_FLASH, FLASH_STATE_ACCESS_WINDOW);
595
596 /** If successful */
597 if (SSP_SUCCESS == err)
598 {
599 /** Set the access window. */
600 err = HW_FLASH_LP_access_window_set(p_ctrl, start_addr, end_addr);
601
602 if (SSP_SUCCESS == err)
603 {
604 /** Return to read mode */
605 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
606 }
607 }
608
609 if (SSP_SUCCESS != err)
610 {
611 /** If there is an error, then reset the Flash. This will clear error flags and exit the P/E mode */
612 HW_FLASH_LP_reset(p_ctrl);
613 }
614
615 /** Release the flash. */
616 flash_ReleaseState();
617 }
618 else
619 {
620 err = SSP_ERR_INVALID_ADDRESS;
621 }
622
623 #else
624 /** If not code flash return error. */
625 err = SSP_ERR_INVALID_ARGUMENT; // For consistency with _LP API we return error if Code Flash not enabled
626 #endif
627 return err;
628 }
629
630 /*******************************************************************************************************************//**
631 * @brief Remove any access window that is configured in the Code Flash. Implements flash_api_t::accessWindowClear.
632 * On successful return from this call all Code Flash is writable.
633 *
634 * @retval SSP_SUCCESS Access window successfully removed.
635 * @retval SSP_ERR_IN_USE FLASH peripheral is busy with a prior operation.
636 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl.
637 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled.
638 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
639 **********************************************************************************************************************/
R_FLASH_LP_AccessWindowClear(flash_ctrl_t * const p_api_ctrl)640 ssp_err_t R_FLASH_LP_AccessWindowClear (flash_ctrl_t * const p_api_ctrl)
641 {
642 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
643
644 /* Eliminate warning if parameter checking is disabled. */
645 SSP_PARAMETER_NOT_USED(p_ctrl);
646 ssp_err_t err = SSP_SUCCESS;
647
648 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
649 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
650 /** If null pointer return error. */
651 SSP_ASSERT(NULL != p_ctrl);
652
653 /** If not open return error. */
654 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
655
656 /** If operation in progress return error. */
657 err = R_FLASH_LP_StatusGet(p_ctrl);
658 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
659 #endif
660
661 /** Update Flash state and enter Code Flash P/E mode */
662 err = setup_for_pe_mode(p_ctrl, FLASH_TYPE_CODE_FLASH, FLASH_STATE_ACCESS_WINDOW);
663
664 /** If successful clear the access window. */
665 if (SSP_SUCCESS == err)
666 {
667 err = HW_FLASH_LP_access_window_clear(p_ctrl);
668
669 /** If successful return to read mode. */
670 if (SSP_SUCCESS == err)
671 {
672 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
673 }
674 }
675
676 /** If failure reset the flash. */
677 if (SSP_SUCCESS != err)
678 {
679 /* If there is an error, then reset the Flash. This will clear error flags and exit the P/E mode */
680 HW_FLASH_LP_reset(p_ctrl);
681 }
682
683 /** Release the flash. */
684 flash_ReleaseState();
685 #else
686 err = SSP_ERR_INVALID_ARGUMENT; ///< Return error if Code Flash not enabled
687 #endif
688
689 return err;
690 }
691
692 /*******************************************************************************************************************//**
693 * @brief Write the ID code provided to the id code registers. Implements flash_api_t::idCodeSet.
694 *
695 * @retval SSP_SUCCESS ID code successfully configured.
696 * @retval SSP_ERR_IN_USE FLASH peripheral is busy with a prior operation.
697 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl.
698 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled.
699 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
700 * @retval SSP_ERR_WRITE_FAILED Status is indicating a Programming error for the requested operation.
701 * @retval SSP_ERR_TIMEOUT Timed out waiting for completion of extra command.
702 **********************************************************************************************************************/
R_FLASH_LP_IdCodeSet(flash_ctrl_t * const p_api_ctrl,uint8_t const * const p_id_code,flash_id_code_mode_t mode)703 ssp_err_t R_FLASH_LP_IdCodeSet (flash_ctrl_t * const p_api_ctrl,
704 uint8_t const * const p_id_code,
705 flash_id_code_mode_t mode)
706 {
707 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
708
709 ssp_err_t err = SSP_SUCCESS;
710
711 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 1)
712 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
713 /** If null pointer return error. */
714 SSP_ASSERT(NULL != p_ctrl);
715 SSP_ASSERT(NULL != p_id_code);
716
717 /** If control block is not open return error. */
718 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
719 #endif
720 /** Update Flash state and enter Code Flash P/E mode */
721 err = setup_for_pe_mode(p_ctrl, FLASH_TYPE_CODE_FLASH, FLASH_STATE_ID_CODE);
722
723 /** If successful set the id code. */
724 if (SSP_SUCCESS == err)
725 {
726 err = HW_FLASH_LP_set_id_code(p_ctrl, p_id_code, mode);
727 }
728
729 /** If successful return to read mode. Otherwise reset the flash. */
730 if (SSP_SUCCESS == err)
731 {
732 /* Return to read mode*/
733 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
734 }
735 else
736 {
737 /* If there is an error, then reset the FCU: This will clear error flags and exit the P/E mode*/
738 HW_FLASH_LP_reset(p_ctrl);
739 }
740
741 /** Release the flash. */
742 flash_ReleaseState();
743
744 #else
745 /* Eliminate warning if code flash programming is disabled. */
746 SSP_PARAMETER_NOT_USED(p_ctrl);
747 SSP_PARAMETER_NOT_USED(p_id_code);
748 SSP_PARAMETER_NOT_USED(mode);
749
750 err = SSP_ERR_INVALID_ARGUMENT; // For consistency with _LP API we return error if Code Flash not enabled
751 #endif
752 /** Return status. */
753 return err;
754 }
755
756 /*******************************************************************************************************************//**
757 * @brief Reset the FLASH peripheral. Implements flash_api_t::reset.
758 *
759 * No attempt is made to grab the Flash software lock before executing the reset since the assumption is that a reset
760 * will terminate any existing operation.
761 *
762 * @retval SSP_SUCCESS Flash circuit successfully reset.
763 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
764 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
765 **********************************************************************************************************************/
R_FLASH_LP_Reset(flash_ctrl_t * const p_api_ctrl)766 ssp_err_t R_FLASH_LP_Reset (flash_ctrl_t * const p_api_ctrl)
767 {
768 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
769
770 ssp_err_t err = SSP_SUCCESS;
771
772 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
773 /** If null pointer return error. */
774 SSP_ASSERT(NULL != p_ctrl);
775
776 /** If not open return error */
777 FLASH_ERROR_RETURN(!(FLASH_OPEN != p_ctrl->opened), SSP_ERR_NOT_OPEN);
778 #endif
779
780 /** Reset the flash. */
781 HW_FLASH_LP_reset(p_ctrl);
782
783 /** Release the flash. */
784 flash_ReleaseState();
785
786 return err;
787 }
788
789 /******************************************************************************************************************//**
790 * @brief Select which block is used as the startup area block. Implements flash_api_t::startupAreaSelect.
791 *
792 * Selects which block - Default (Block 0) or Alternate (Block 1) is used as the startup area block.
793 * The provided parameters determine which block will become the active startup block and whether that
794 * action will be immediate (but temporary), or permanent subsequent to the next reset.
795 * Doing a temporary switch might appear to have limited usefulness. If there is an access window
796 * in place such that Block 0 is write protected, then one could do a temporary switch, update the
797 * block and switch them back without having to touch the access window.
798 *
799 * @retval SSP_SUCCESS Start-up area successfully toggled.
800 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
801 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
802 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
803 **********************************************************************************************************************/
R_FLASH_LP_StartUpAreaSelect(flash_ctrl_t * const p_api_ctrl,flash_startup_area_swap_t swap_type,bool is_temporary)804 ssp_err_t R_FLASH_LP_StartUpAreaSelect (flash_ctrl_t * const p_api_ctrl,
805 flash_startup_area_swap_t swap_type,
806 bool is_temporary)
807 {
808 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
809
810 ssp_err_t err = SSP_SUCCESS;
811
812 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
813 /** If null pointer return error. */
814 SSP_ASSERT(NULL != p_ctrl);
815
816 /** If not open return error. */
817 FLASH_ERROR_RETURN((FLASH_OPEN == p_ctrl->opened), SSP_ERR_NOT_OPEN);
818 #endif
819
820 /** If the swap type is BTFLG and the operation is temporary there's nothing to do. Return success. */
821 if ((swap_type == FLASH_STARTUP_AREA_BTFLG) && (is_temporary == false))
822 {
823 return err;
824 }
825
826 /** Update Flash state and enter the respective Code or Data Flash P/E mode. */
827 err = setup_for_pe_mode(p_ctrl, FLASH_TYPE_CODE_FLASH, FLASH_STATE_STARTUP_AREA);
828
829 /** If successful call the temporary or boot startup area set functions depending on the users flag. */
830 if (err == SSP_SUCCESS)
831 {
832 if (is_temporary == true)
833 {
834 err = HW_FLASH_LP_set_startup_area_temporary(p_ctrl, swap_type);
835 }
836 else
837 {
838 err = HW_FLASH_LP_set_startup_area_boot(p_ctrl, swap_type);
839 }
840 }
841
842 /** If successful return to read mode otherwise reset the flash. */
843 if (SSP_SUCCESS == err)
844 {
845 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
846 }
847 else
848 {
849 /* If there is an error, then reset the Flash. This will clear error flags and exit the P/E mode */
850 HW_FLASH_LP_reset(p_ctrl);
851 }
852
853 /** Release the flash. */
854 flash_ReleaseState();
855 return err;
856 }
857
858
859 /******************************************************************************************************************//**
860 * @brief Indicate to the already open Flash API that the FCLK has changed. Implements r_flash_t::updateFlashClockFreq.
861 *
862 * This could be the case if the application has changed the system clock, and therefore the FCLK.
863 * Failure to call this function subsequent to changing the FCLK could result in damage to the flash macro.
864 * This function uses R_CGC_SystemClockFreqGet() to get the current FCLK frequency.
865 *
866 *
867 * @retval SSP_SUCCESS Start-up area successfully toggled.
868 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
869 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl
870 * @retval SSP_ERR_NOT_OPEN Flash API has not yet been opened.
871 **********************************************************************************************************************/
R_FLASH_LP_UpdateFlashClockFreq(flash_ctrl_t * const p_api_ctrl)872 ssp_err_t R_FLASH_LP_UpdateFlashClockFreq (flash_ctrl_t * const p_api_ctrl)
873 {
874 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
875
876 ssp_err_t err = SSP_SUCCESS;
877
878 #if (FLASH_CFG_PARAM_CHECKING_ENABLE)
879 /** If null pointer return error. */
880 SSP_ASSERT(NULL != p_ctrl);
881
882 /** If the flash api is not open return an error. */
883 FLASH_ERROR_RETURN(FLASH_OPEN == p_ctrl->opened, SSP_ERR_NOT_OPEN);
884 #endif
885
886 /** Lock the flash state. If failure return error. */
887 FLASH_ERROR_RETURN(SSP_SUCCESS == flash_lock_state(FLASH_UPDATE_FCLK), SSP_ERR_IN_USE);
888
889 /** Setup the Flash. */
890 err = flash_setup(p_ctrl); // Check FCLK, calculate timeout values
891
892 /** Release the flash. */
893 flash_ReleaseState();
894
895 return err;
896 }
897 /*******************************************************************************************************************//**
898 * @brief Returns the information about the flash regions. Implements
899 * flash_api_t::infoGet.
900 *
901 * @retval SSP_SUCCESS Successful retrieved the request information.
902 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl or p_info.
903 **********************************************************************************************************************/
R_FLASH_LP_InfoGet(flash_ctrl_t * const p_api_ctrl,flash_info_t * const p_info)904 ssp_err_t R_FLASH_LP_InfoGet (flash_ctrl_t * const p_api_ctrl, flash_info_t * const p_info)
905 {
906 #if FLASH_CFG_PARAM_CHECKING_ENABLE
907 /** If null pointers return error. */
908 SSP_ASSERT(NULL != p_api_ctrl);
909 SSP_ASSERT(NULL != p_info);
910 #endif
911
912 /** Copy the region data to the info structure. */
913 p_info->code_flash = g_flash_code_region;
914 p_info->data_flash = g_flash_data_region;
915
916 return SSP_SUCCESS;
917 }
918 /*******************************************************************************************************************//**
919 * @brief Release any resources that were allocated by the Flash API. Implements flash_api_t::close.
920 *
921 * @retval SSP_SUCCESS Successful close.
922 * @retval SSP_ERR_ASSERTION NULL provided for p_ctrl or p_cfg.
923 **********************************************************************************************************************/
R_FLASH_LP_Close(flash_ctrl_t * const p_api_ctrl)924 ssp_err_t R_FLASH_LP_Close (flash_ctrl_t * const p_api_ctrl)
925 {
926 flash_lp_instance_ctrl_t * p_ctrl = (flash_lp_instance_ctrl_t *) p_api_ctrl;
927
928 /* Eliminate warning if parameter checking is disabled. */
929 SSP_PARAMETER_NOT_USED(p_ctrl);
930
931 ssp_err_t err = SSP_SUCCESS;
932
933 #if FLASH_CFG_PARAM_CHECKING_ENABLE
934 /** If null pointer return error. */
935 SSP_ASSERT(NULL != p_ctrl);
936 #endif
937
938 ssp_feature_t ssp_feature = {{(ssp_ip_t) 0U}};
939 ssp_feature.channel = 0U;
940 ssp_feature.unit = 0U;
941 ssp_feature.id = SSP_IP_FCU;
942
943 /** Unlock the flash hardware. */
944 R_BSP_HardwareUnlock(&ssp_feature);
945
946 /** Disable the flash interrupt. */
947 HW_FLASH_LP_irq_cfg(false, NULL, p_ctrl->irq);
948
949 /** Mark the control block as closed. */
950 p_ctrl->opened = false;
951
952 /** Release the lock */
953 flash_ReleaseState();
954
955 return err;
956 }
957
958 /*******************************************************************************************************************//**
959 * @brief Get FLASH HAL driver version.
960 *
961 * @retval SSP_SUCCESS - operation performed successfully
962 * @note This function is reentrant.
963 **********************************************************************************************************************/
R_FLASH_LP_VersionGet(ssp_version_t * const p_version)964 ssp_err_t R_FLASH_LP_VersionGet (ssp_version_t * const p_version)
965 {
966 #if FLASH_CFG_PARAM_CHECKING_ENABLE
967 /** If null pointer return error. */
968 SSP_ASSERT(NULL != p_version);
969 #endif
970
971 /** Return the version id of the flash lp module. */
972 p_version->version_id = g_flash_lp_version.version_id;
973 return SSP_SUCCESS;
974 } /* End of function R_FLASH_LP_VersionGet() */
975
976 /*******************************************************************************************************************//**
977 * @} (end addtogroup FLASH)
978 **********************************************************************************************************************/
979
980 /*******************************************************************************************************************//**
981 * @brief This function attempts to change the flash state to the new requested state.
982 * This can only happen if we are able to take the FLASH lock. If the lock is currently in use then
983 * we will return FLASH_ERR_BUSY, otherwise we will take the lock and change the state.
984 *
985 * @param[in] new_state Which state to attempt to transition to.
986 * @retval SSP_SUCCESS Successful.
987 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
988 **********************************************************************************************************************/
flash_lock_state(flash_states_t new_state)989 static ssp_err_t flash_lock_state (flash_states_t new_state)
990 {
991 /** Check to see if lock was successfully taken */
992 if (R_BSP_SoftwareLock(&g_flash_Lock) == SSP_SUCCESS)
993 {
994 /** Lock taken, we can change state */
995 g_flash_state = new_state;
996
997 /** Return success */
998 return SSP_SUCCESS;
999 }
1000 else
1001 {
1002 /** Another operation is on-going */
1003 return SSP_ERR_IN_USE;
1004 }
1005 }
1006
1007 /*******************************************************************************************************************//**
1008 * @brief This function releases the flash state so another flash operation can take place.
1009 * This function is called by both the HLD and LLD layers (interrupt routines).
1010 *
1011 * @retval None
1012 **********************************************************************************************************************/
flash_ReleaseState(void)1013 void flash_ReleaseState (void)
1014 {
1015 /** Done with current operation */
1016 g_flash_state = FLASH_STATE_READY;
1017
1018 /** Release hold on lock */
1019 R_BSP_SoftwareUnlock(&g_flash_Lock);
1020 }
1021
1022 /*******************************************************************************************************************//**
1023 * @brief This function places the flash in the requested Code or Data P/E mode.
1024 *
1025 * @param[in] flash_type FLASH_TYPE_CODE_FLASH or FLASH_TYPE_DATA_FLASH.
1026 * @param[in] p_ctrl Control Instance
1027 * @param[in] flash_state Desired Flash state to transition into (ie FLASH_STATE_WRITING).
1028 * @retval SSP_SUCCESS Successful.
1029 * @retval SSP_ERR_INVALID_ARGUMENT Supplied flash_type was something other than FLASH_TYPE_CODE_FLASH or
1030 * FLASH_TYPE_DATA_FLASH.
1031 * @retval SSP_ERR_IN_USE Flash is busy with an on-going operation.
1032 **********************************************************************************************************************/
setup_for_pe_mode(flash_lp_instance_ctrl_t * const p_ctrl,flash_type_t flash_type,flash_states_t flash_state)1033 static ssp_err_t setup_for_pe_mode (flash_lp_instance_ctrl_t * const p_ctrl, flash_type_t flash_type, flash_states_t flash_state)
1034 {
1035 ssp_err_t err = SSP_SUCCESS;
1036
1037 /** If the API is not ready return error. */
1038 if (g_flash_state != FLASH_STATE_READY)
1039 {
1040 err = SSP_ERR_IN_USE;
1041 }
1042 else
1043 {
1044 /** Lock the flash state. If failure return error. */
1045 if (SSP_SUCCESS != flash_lock_state(flash_state))
1046 {
1047 err = SSP_ERR_IN_USE;
1048 }
1049 else
1050 {
1051 /** Enter PE mode. If failure release software lock. */
1052 err = HW_FLASH_LP_pe_mode_enter(p_ctrl, flash_type);
1053 if (SSP_SUCCESS != err)
1054 {
1055 flash_ReleaseState();
1056 }
1057 }
1058 }
1059
1060 /** Return status. */
1061 return err;
1062 }
1063
1064 /*******************************************************************************************************************//**
1065 * @brief This function will validate the supplied address, and return information about the block in which
1066 * it resides.
1067 *
1068 * @param[in] addr Code or Data Flash address to return info for.
1069 * @param[out] p_block_info Pointer to a caller allocated flash_block_info_t structure which will be filled
1070 * in by this function.
1071 * @retval false Supplied address is neither a valid Code or Data Flash address for this part.
1072 * @retval true Supplied address is valid and p_block_infocontains the details on this addresses block
1073 **********************************************************************************************************************/
flash_get_block_info(uint32_t addr,flash_block_info_t * p_block_info)1074 bool flash_get_block_info (uint32_t addr, flash_block_info_t * p_block_info)
1075 {
1076 const flash_fmi_block_info_t * pBInfo = NULL;
1077 uint32_t num_sections = 0U;
1078 uint32_t bnum = 0U;
1079 uint32_t num_tbl_entries = 0U;
1080 bool ret_value = false;
1081
1082 p_block_info->total_blocks = 0U;
1083
1084 /** Loop over code flash regions */
1085 for (uint32_t i = 0U; i < g_flash_code_region.num_regions; i++)
1086 {
1087 /** If the address is within the code flash region save region information*/
1088 if ((addr >= g_flash_code_region.p_block_array[i].block_section_st_addr) &&
1089 (addr <= g_flash_code_region.p_block_array[i].block_section_end_addr))
1090 {
1091 p_block_info->is_code_flash_addr = true;
1092 p_block_info->flash_type = FLASH_TYPE_CODE_FLASH;
1093 num_tbl_entries = g_flash_code_region.num_regions;
1094 pBInfo = &g_flash_code_region.p_block_array[0];
1095 }
1096 }
1097 /** Loop over data flash regions */
1098 for (uint32_t i = 0U; i < g_flash_data_region.num_regions; i++)
1099 {
1100 /** If the address is within the data flash region save region information */
1101 if ((addr >= g_flash_data_region.p_block_array[i].block_section_st_addr) &&
1102 (addr <= g_flash_data_region.p_block_array[i].block_section_end_addr))
1103 {
1104 p_block_info->is_code_flash_addr = false;
1105 p_block_info->flash_type = FLASH_TYPE_DATA_FLASH;
1106 num_tbl_entries = g_flash_data_region.num_regions;
1107 pBInfo = &g_flash_data_region.p_block_array[0];
1108 }
1109 }
1110
1111 /** Loop over all regions in the section of flash containing the address. */
1112 while (num_sections < num_tbl_entries)
1113 {
1114 ret_value = true;
1115 num_sections++;
1116
1117 /** Calculate the number of blocks in the region */
1118 uint32_t num_blocks = (((pBInfo->block_section_end_addr + 1U) - pBInfo->block_section_st_addr) /
1119 pBInfo->block_size);
1120
1121 /** If the address is within the region save detailed region information. */
1122 if ((addr >= pBInfo->block_section_st_addr) && (addr <= pBInfo->block_section_end_addr))
1123 {
1124 bnum = ((addr - pBInfo->block_section_st_addr) / pBInfo->block_size);
1125
1126 p_block_info->this_block_st_addr = pBInfo->block_section_st_addr + (bnum * pBInfo->block_size);
1127 p_block_info->this_block_end_addr = (p_block_info->this_block_st_addr + pBInfo->block_size) - 1;
1128 p_block_info->this_block_number = bnum + p_block_info->total_blocks;
1129 p_block_info->block_section_st_addr = pBInfo->block_section_st_addr;
1130 p_block_info->block_section_end_addr = pBInfo->block_section_end_addr;
1131 p_block_info->block_size = pBInfo->block_size;
1132 p_block_info->num_blocks = num_blocks;
1133 p_block_info->min_program_size = pBInfo->block_size_write;
1134 }
1135
1136 /** Update the end of memory address and go to the next region. */
1137 p_block_info->memory_end_addr = pBInfo->block_section_end_addr;
1138 pBInfo++;
1139
1140 /** Increment the total block count by the number of blocks in the region. */
1141 p_block_info->total_blocks += num_blocks;
1142 }
1143
1144 return ret_value;
1145 }
1146
1147 /*******************************************************************************************************************//**
1148 * @brief This function verifies that FCLK falls within the allowable range and calculates the timeout values
1149 * based on the current FCLK frequency.
1150 *
1151 * @retval SSP_SUCCESS Success
1152 * @retval SSP_ERR_FCLK FCLK must be >= 4 MHz.
1153 * @retval SSP_ERR_INVALID_ARGUMENT Invalid argument provided to CGC call. Should never occur...
1154 **********************************************************************************************************************/
flash_setup(flash_lp_instance_ctrl_t * const p_ctrl)1155 static ssp_err_t flash_setup (flash_lp_instance_ctrl_t * const p_ctrl)
1156 {
1157 ssp_err_t err;
1158 bsp_feature_flash_lp flash_lp_feature = {0U};
1159
1160 /** Get BSP specific information about the flash LP. */
1161 /* We need clock frequencies to calculate the worst case timeout values. Note S124 and S128 do not have a
1162 * separate FCLK, they use ICLK */
1163 R_BSP_FeatureFlashLpGet(&flash_lp_feature);
1164
1165 /** Save the flash sp information to the global parameters structure. */
1166 g_current_parameters.flash_cf_macros = flash_lp_feature.flash_cf_macros; // S3A7 and S3A1 have 2 CF macros. That's a special case for blank check.
1167 g_current_parameters.cf_macro_size = flash_lp_feature.cf_macro_size;
1168 g_current_parameters.cf_memory_st_addr = g_flash_code_region.p_block_array[0].block_section_st_addr; // Starting memory address for Code Flash
1169 g_current_parameters.df_memory_st_addr = g_flash_data_region.p_block_array[0].block_section_st_addr; // Starting memory address for Data Flash
1170
1171 /** Get the frequency of the clock driving the flash. If failure return error. */
1172 err = g_cgc_on_cgc.systemClockFreqGet((cgc_system_clocks_t)flash_lp_feature.flash_clock_src, &g_current_parameters.flash_clock_freq);
1173 if (SSP_SUCCESS == err)
1174 {
1175 /** FCLK must be a minimum of 4 MHz for Flash operations. If not return error. */
1176 if (g_current_parameters.flash_clock_freq < MINIMUM_SUPPORTED_FCLK_FREQ)
1177 {
1178 err = SSP_ERR_FCLK;
1179 }
1180 else
1181 {
1182 /** Get the frequency of the system clock. If failure return error. */
1183 err = g_cgc_on_cgc.systemClockFreqGet(CGC_SYSTEM_CLOCKS_ICLK, &g_current_parameters.system_clock_freq);
1184 }
1185 }
1186
1187 if (SSP_SUCCESS == err)
1188 {
1189 /** Initialize the flash timeout calculations and transfer global parameters to code and data flash layers. */
1190 HW_FLASH_LP_init(p_ctrl, &g_current_parameters);
1191 HW_FLASH_LP_code_flash_set_flash_settings(&g_current_parameters); // Give HW layer below access to the configured settings
1192 HW_FLASH_LP_data_flash_set_flash_settings(&g_current_parameters); // Give HW layer below access to the configured settings
1193
1194 /** Enable the DataFlash */
1195 HW_FLASH_LP_dataflash_enable(p_ctrl);
1196 }
1197
1198 return err;
1199 }
1200
1201 /*******************************************************************************************************************//**
1202 * @brief This function performs the parameter checking required by the R_FLASH_LP_Write() function.
1203 *
1204 * @retval SSP_SUCCESS Parameter checking completed without error.
1205 * @retval SSP_ERR_INVALID_SIZE Number of bytes provided was not a multiple of the programming size or exceeded
1206 * the maximum range.
1207 * @retval SSP_ERR_NOT_OPEN The Flash API is not Open.
1208 * @retval SSP_ERR_INVALID_ADDRESS Invalid address was input or address not on programming boundary.
1209 **********************************************************************************************************************/
flash_write_parameter_checking(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t flash_address,uint32_t const num_bytes)1210 static ssp_err_t flash_write_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t flash_address, uint32_t const num_bytes)
1211 {
1212 /** If null control block return error. */
1213 SSP_ASSERT(NULL != p_ctrl);
1214 volatile bool result1 = false;
1215 volatile bool result2 = false;
1216 volatile bool result3 = false;
1217
1218 result1 = (bool)(flash_address >= g_block_info.block_section_st_addr);
1219 result2 = (bool)(flash_address <= g_block_info.block_section_end_addr);
1220 result3 = (bool)(!(flash_address & (g_block_info.min_program_size - 1U)));
1221
1222 /** If invalid address return error. */
1223 FLASH_ERROR_RETURN((result1 && result2 && result3), SSP_ERR_INVALID_ADDRESS);
1224
1225 result1 = (bool)(((num_bytes - 1U) + flash_address) > g_block_info.block_section_end_addr);
1226 result2 = (bool)((num_bytes & (g_block_info.min_program_size - 1U)));
1227 result3 = (bool)(0 == num_bytes);
1228
1229 /** If invalid number of bytes return error. */
1230 FLASH_ERROR_RETURN(!(result1 || result2 || result3), SSP_ERR_INVALID_SIZE);
1231
1232 return(SSP_SUCCESS);
1233 }
1234
1235 /*******************************************************************************************************************//**
1236 * @brief This function does the completion setup for the R_FLASH_HP_Open() function.
1237 *
1238 **********************************************************************************************************************/
flash_open_setup(flash_lp_instance_ctrl_t * const p_ctrl,ssp_feature_t * p_ssp)1239 static ssp_err_t flash_open_setup (flash_lp_instance_ctrl_t * const p_ctrl, ssp_feature_t *p_ssp)
1240 {
1241 ssp_err_t err = SSP_SUCCESS;
1242
1243 /** Release state so other operations can be performed. */
1244 flash_ReleaseState();
1245
1246 /** Flash setup. */
1247 err = flash_setup(p_ctrl); // Check FCLK, calculate timeout values
1248
1249 /** If successful mark control block open otherwise release hardware lock and return error. */
1250 if (err != SSP_SUCCESS)
1251 {
1252 /* Return the hardware lock for the Flash */
1253 R_BSP_HardwareUnlock(p_ssp);
1254 }
1255 else
1256 {
1257 p_ctrl->opened = FLASH_OPEN;
1258 }
1259
1260 return err;
1261 }
1262 /*******************************************************************************************************************//**
1263 * @brief This function initiates the write sequence for the R_FLASH_LP_Write() function.
1264 *
1265 **********************************************************************************************************************/
flash_write_initiate(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const src_start_address,uint32_t dest_start_address,uint32_t num_bytes)1266 static ssp_err_t flash_write_initiate (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const src_start_address, uint32_t dest_start_address, uint32_t num_bytes)
1267 {
1268 ssp_err_t err;
1269
1270 /** Set up PE mode */
1271 err = setup_for_pe_mode(p_ctrl, g_block_info.flash_type, FLASH_STATE_WRITING);
1272
1273 /** If successful */
1274 if (SSP_SUCCESS == err)
1275 {
1276 /** Configure the current parameters for code flash or data flash depending on address. */
1277 if (g_block_info.is_code_flash_addr == true)
1278 {
1279 g_current_parameters.wait_cnt = g_current_parameters.wait_max_write_cf;
1280 g_current_parameters.current_operation = FLASH_OPERATION_CF_WRITE;
1281 g_current_parameters.min_pgm_size = (g_block_info.min_program_size >> 1);
1282 }
1283 else
1284 {
1285 g_current_parameters.wait_cnt = g_current_parameters.wait_max_write_df;
1286 g_current_parameters.min_pgm_size = g_block_info.min_program_size; // For MF3 DF it's always 1
1287
1288 if (g_current_parameters.bgo_enabled_df == false)
1289 {
1290 g_current_parameters.current_operation = FLASH_OPERATION_DF_WRITE;
1291 }
1292 else
1293 {
1294 g_current_parameters.current_operation = FLASH_OPERATION_DF_BGO_WRITE;
1295 }
1296 }
1297
1298 /** Write the data */
1299 err = HW_FLASH_LP_write(p_ctrl, src_start_address, dest_start_address, num_bytes, g_block_info.min_program_size);
1300 if (SSP_SUCCESS == err)
1301 {
1302 /** If in non-BGO mode, then current operation is completed. Exit PE mode and return status */
1303 if (g_current_parameters.current_operation != FLASH_OPERATION_DF_BGO_WRITE)
1304 {
1305 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
1306 }
1307 }
1308 }
1309 return(err);
1310 }
1311
1312
1313 /*******************************************************************************************************************//**
1314 * @brief This function performs the final cleanup for the erase, write and blankcheck functions. Executes a reset
1315 * if any error has been indicated. Releases the state if the current operation is NOT BGO.
1316 *
1317 **********************************************************************************************************************/
flash_operation_complete(flash_lp_instance_ctrl_t * const p_ctrl,ssp_err_t err)1318 static void flash_operation_complete (flash_lp_instance_ctrl_t * const p_ctrl, ssp_err_t err)
1319 {
1320 /** SSP_ERR_IN_USE will be returned if we are in the process of executing a BGO operation. In this case we do
1321 * not want to take any action as that will terminate the in process operation */
1322 if ((g_current_parameters.bgo_enabled_df == true) &&
1323 ((g_current_parameters.current_operation == FLASH_OPERATION_DF_BGO_ERASE) ||
1324 (g_current_parameters.current_operation == FLASH_OPERATION_DF_BGO_WRITE) ||
1325 (g_current_parameters.current_operation == FLASH_OPERATION_DF_BGO_BLANKCHECK)))
1326 {
1327 if ((err == SSP_ERR_IN_USE) || (err == SSP_SUCCESS))
1328 {
1329 return;
1330 }
1331 }
1332 else
1333 {
1334 /** We are not in a BGO mode, so this operation is complete. Release the software lock. */
1335 flash_ReleaseState();
1336
1337 /** If failure reset the flash. */
1338 if (err != SSP_SUCCESS)
1339 {
1340 HW_FLASH_LP_reset(p_ctrl);
1341 }
1342 }
1343 }
1344
1345 #if (FLASH_CFG_PARAM_CHECKING_ENABLE == 1)
1346 /*******************************************************************************************************************//**
1347 * @brief This function performs the parameter checking required by the R_FLASH_HP_Erase() function.
1348 *
1349 * @retval SSP_SUCCESS Parameter checking completed without error.
1350 * @retval SSP_ERR_INVALID_BLOCKS Invalid number of blocks specified
1351 * @retval SSP_ERR_NOT_OPEN The Flash API is not Open.
1352 * @retval SSP_ERR_INVALID_ARGUMENT Code Flash Programming is not enabled and a request to erase CF was requested.
1353 **********************************************************************************************************************/
flash_erase_parameter_checking(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const num_blocks)1354 static ssp_err_t flash_erase_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const num_blocks)
1355 {
1356 /** If null pointer return error. */
1357 SSP_ASSERT(NULL != p_ctrl);
1358 volatile bool result1 = false;
1359 volatile bool result2 = false;
1360 volatile bool result3 = false;
1361
1362 /** If invalid number of blocks return error. */
1363 result1 = (bool)(num_blocks > g_block_info.total_blocks);
1364 result2 = (bool)(num_blocks > (g_block_info.total_blocks - g_block_info.this_block_number));
1365 result3 = (bool)(num_blocks <= 0U);
1366
1367 FLASH_ERROR_RETURN(!(result1 || result2 || result3), SSP_ERR_INVALID_BLOCKS);
1368
1369 /** If not open return error */
1370 FLASH_ERROR_RETURN((FLASH_OPEN == p_ctrl->opened), SSP_ERR_NOT_OPEN);
1371
1372 /** If Code Flash Programming is not enabled, then the requisite functions are NOT in RAM and we can not allow an Erase request for
1373 * Code Flash */
1374 #if (FLASH_CFG_PARAM_CODE_FLASH_PROGRAMMING_ENABLE == 0)
1375 FLASH_ERROR_RETURN((g_block_info.is_code_flash_addr == false), SSP_ERR_INVALID_ARGUMENT);
1376 #endif
1377
1378 return(SSP_SUCCESS);
1379 }
1380 #endif
1381 /*******************************************************************************************************************//**
1382 * @brief This function performs the parameter checking required by the R_FLASH_HP_BlankCheck() function.
1383 *
1384 * @retval SSP_SUCCESS Parameter checking completed without error.
1385 * @retval SSP_ERR_INVALID_BLOCKS Invalid number of blocks specified
1386 * @retval SSP_ERR_NOT_OPEN The Flash API is not Open.
1387 * @retval SSP_ERR_IN_USE The Flash peripheral is busy with a prior on-going transaction.
1388 **********************************************************************************************************************/
flash_blank_check_parameter_checking(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const address,uint32_t num_bytes)1389 static ssp_err_t flash_blank_check_parameter_checking (flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const address, uint32_t num_bytes)
1390 {
1391 ssp_err_t err = SSP_SUCCESS;
1392
1393 SSP_ASSERT(NULL != p_ctrl);
1394
1395 /** If not open return error. */
1396 FLASH_ERROR_RETURN((FLASH_OPEN == p_ctrl->opened), SSP_ERR_NOT_OPEN);
1397
1398 /** If invalid address or bytes return error. */
1399 err = flash_blank_check_address_checking (address, num_bytes);
1400 FLASH_ERROR_RETURN((err == SSP_SUCCESS), err);
1401
1402 /* If the flash is not in the ready state return error. */
1403 FLASH_ERROR_RETURN((g_flash_state == FLASH_STATE_READY), SSP_ERR_IN_USE);
1404
1405 return(err);
1406 }
1407
1408 /*******************************************************************************************************************//**
1409 * @brief This function performs the address checking required by the R_FLASH_HP_BlankCheck() function.
1410 *
1411 * @retval SSP_SUCCESS Parameter checking completed without error.
1412 * @retval SSP_ERR_INVALID_ADDRESS Invalid data flash address was input.
1413 * @retval SSP_ERR_INVALID_SIZE 'num_bytes' was either too large or not aligned for the CF/DF boundary size.
1414 **********************************************************************************************************************/
flash_blank_check_address_checking(uint32_t const address,uint32_t num_bytes)1415 static ssp_err_t flash_blank_check_address_checking (uint32_t const address, uint32_t num_bytes)
1416 {
1417 ssp_err_t err = SSP_SUCCESS;
1418 volatile bool result1 = false;
1419 volatile bool result2 = false;
1420
1421 result1 = (bool)(address >= g_block_info.block_section_st_addr);
1422 result2 = (bool)(address <= g_block_info.block_section_end_addr);
1423 FLASH_ERROR_RETURN((result1 && result2), SSP_ERR_INVALID_ADDRESS);
1424
1425
1426 result1 = (bool)((num_bytes + address) > (g_block_info.block_section_end_addr + 1U));
1427 result2 = (bool)(0 == num_bytes);
1428
1429 FLASH_ERROR_RETURN(!(result1 || result2), SSP_ERR_INVALID_SIZE);
1430
1431
1432 /** Is this a request to Blank Check Data Flash?. If so, num_bytes must be a multiple of the programming size */
1433 if (g_block_info.is_code_flash_addr == false)
1434 {
1435 FLASH_ERROR_RETURN(!(num_bytes & (g_block_info.min_program_size - 1U)), SSP_ERR_INVALID_SIZE);
1436 }
1437
1438 return(err);
1439 }
1440
1441
1442
1443 /*******************************************************************************************************************//**
1444 * @brief This function performs the Blank check phase required by the R_FLASH_HP_BlankCheck() function.
1445 *
1446 * @retval SSP_SUCCESS Setup completed completed without error.
1447 * @retval SSP_ERR_PE_FAILURE Failed to enter P/E mode
1448 **********************************************************************************************************************/
1449
flash_blank_check_initiate(flash_lp_instance_ctrl_t * const p_ctrl,uint32_t const address,uint32_t num_bytes,flash_result_t * p_blank_check_result)1450 static ssp_err_t flash_blank_check_initiate ( flash_lp_instance_ctrl_t * const p_ctrl, uint32_t const address, uint32_t num_bytes, flash_result_t *p_blank_check_result)
1451 {
1452 ssp_err_t err = SSP_SUCCESS;
1453
1454 /** Configure the current operation and wait count based on the number of bytes and if it's a data flash or code flash operation. */
1455 /* Is this a request to Blank check Code Flash? */
1456 if (g_block_info.is_code_flash_addr == true)
1457 {
1458 /* This is a request to Blank check Code Flash */
1459 /*No errors in parameters. Enter Code Flash PE mode*/
1460 /* wait_max_blank_check specifies the wait time for a 4 ROM byte blank check.
1461 * num_bytes is divided by 4 and then multiplied to calculate the wait time for the entire operation */
1462 if (num_bytes < (uint32_t)4)
1463 {
1464 g_current_parameters.wait_cnt = g_current_parameters.wait_max_blank_check * num_bytes;
1465 }
1466 else
1467 {
1468 g_current_parameters.wait_cnt = (g_current_parameters.wait_max_blank_check * (num_bytes >> 2));
1469 }
1470 g_current_parameters.current_operation = FLASH_OPERATION_CF_BLANKCHECK;
1471 }
1472 else
1473 {
1474 /* This is a request to Blank check Data Flash */
1475 /* No errors in parameters. Enter Data Flash PE mode*/
1476 /* wait_max_blank_check specifies the wait time for a 4 ROM byte blank check. This is the same as the
1477 * wait time for a 1 byte Data Flash blankcheck.*/
1478 g_current_parameters.wait_cnt = g_current_parameters.wait_max_blank_check * num_bytes;
1479 if (g_current_parameters.bgo_enabled_df == false)
1480 {
1481 g_current_parameters.current_operation = FLASH_OPERATION_DF_BLANKCHECK;
1482 }
1483 else
1484 {
1485 g_current_parameters.current_operation = FLASH_OPERATION_DF_BGO_BLANKCHECK;
1486 }
1487 }
1488
1489 /** Start the Blank check operation. */
1490 /* If BGO is enabled then the result of the Blank check will be
1491 * available when the interrupt occurs and p_blank_check_result will contain FLASH_RESULT_BGO_ACTIVE */
1492 err = HW_FLASH_LP_blankcheck(p_ctrl, address, num_bytes, p_blank_check_result);
1493
1494 if (SSP_SUCCESS == err)
1495 {
1496 /** If in non-BGO mode, then current operation is complete. Exit PE mode and return status */
1497 if (g_current_parameters.current_operation != FLASH_OPERATION_DF_BGO_BLANKCHECK)
1498 {
1499 err = HW_FLASH_LP_pe_mode_exit(p_ctrl);
1500 g_current_parameters.current_operation = FLASH_OPERATION_IDLE;
1501 }
1502 }
1503 return(err);
1504 }
1505
1506 /*******************************************************************************************************************//**
1507 * @brief This function initializes data required by the Flash based on information read from the FMI.
1508 *
1509 * @retval SSP_SUCCESS FMI based setup success.
1510 * @retval SSP_ERR_IN_USE The Flash peripheral is busy with a prior on-going transaction.
1511 * @retval SSP_ERR_ASSERTION Problem getting FMI information.
1512 * @retval SSP_ERR_HW_LOCKED Unable to get the HW lock for the Flash.
1513 *
1514 **********************************************************************************************************************/
flash_fmi_setup(flash_lp_instance_ctrl_t * const p_ctrl,flash_cfg_t const * const p_cfg,ssp_feature_t * p_ssp)1515 static ssp_err_t flash_fmi_setup (flash_lp_instance_ctrl_t * const p_ctrl, flash_cfg_t const * const p_cfg, ssp_feature_t *p_ssp)
1516 {
1517 ssp_err_t err = SSP_SUCCESS;
1518
1519 p_ssp->id = SSP_IP_CFLASH;
1520 p_ssp->channel = 0U;
1521 p_ssp->unit = 0U;
1522 fmi_feature_info_t info = {0};
1523
1524 /** Initialize the code flash region data. */
1525 g_fmi_on_fmi.productFeatureGet(p_ssp, &info);
1526 g_flash_code_region.num_regions = info.channel_count;
1527 g_flash_code_region.p_block_array = (flash_fmi_block_info_t const *) info.ptr_extended_data;
1528
1529 /** Initialize the data flash region data. */
1530 p_ssp->id = SSP_IP_DFLASH;
1531 g_fmi_on_fmi.productFeatureGet(p_ssp, &info);
1532 g_flash_data_region.num_regions = info.channel_count;
1533 g_flash_data_region.p_block_array = (flash_fmi_block_info_t const *) info.ptr_extended_data;
1534
1535 p_ssp->id = SSP_IP_FCU;
1536 err = g_fmi_on_fmi.productFeatureGet(p_ssp, &info);
1537 FLASH_ERROR_RETURN(SSP_SUCCESS == err, err);
1538
1539 p_ctrl->p_reg = (R_FACI_Type *) info.ptr;
1540
1541 /** Initialize event information. */
1542 ssp_vector_info_t * p_vector_info;
1543 fmi_event_info_t event_info = {(IRQn_Type) 0};
1544 g_fmi_on_fmi.eventInfoGet(p_ssp, SSP_SIGNAL_FCU_FRDYI, &event_info);
1545 p_ctrl->irq = event_info.irq;
1546 if (SSP_INVALID_VECTOR != p_ctrl->irq)
1547 {
1548 R_SSP_VectorInfoGet(p_ctrl->irq, &p_vector_info);
1549 NVIC_SetPriority(p_ctrl->irq, p_cfg->irq_ipl);
1550 *(p_vector_info->pp_ctrl) = p_ctrl;
1551 }
1552
1553 /** Take the hardware lock for the Flash. If failure return error. */
1554 FLASH_ERROR_RETURN(!(SSP_SUCCESS != R_BSP_HardwareLock(p_ssp)), SSP_ERR_HW_LOCKED);
1555 return(SSP_SUCCESS);
1556 }
1557
1558
1559