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